Skip to content

Commit 6073f71

Browse files
authored
Merge pull request #55 from lokalise/feature/PERF-1401_add_too_big_request_warning
PERF-1401 Add too big response warning
2 parents 23b14eb + 589330c commit 6073f71

File tree

8 files changed

+152
-10
lines changed

8 files changed

+152
-10
lines changed

docs/additional_info/changelog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## 3.6.1 (16-May-2025)
4+
5+
* Add a warning for big projects suggesting to use [async file downloads](https://developers.lokalise.com/reference/download-files-async) endpoint
6+
37
## 3.6.0 (08-May-2025)
48

59
* Add support for [Current contributor](https://developers.lokalise.com/reference/retrieve-me-as-a-contributor) (me) endpoint

lib/elixir_lokalise_api/endpoints/files.ex

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,24 @@ defmodule ElixirLokaliseApi.Files do
2020
Downloads a translation bundle from the project.
2121
"""
2222
def download(project_id, data) do
23-
make_request(:post,
24-
data: data,
25-
url_params: url_params(project_id) ++ [{:_postfix, "download"}],
26-
type: :raw
27-
)
23+
case make_request(:post,
24+
data: data,
25+
url_params: url_params(project_id) ++ [{:_postfix, "download"}],
26+
type: :raw
27+
) do
28+
{:ok, result} ->
29+
if Map.has_key?(result, :_request_too_big) do
30+
IO.warn("""
31+
Your project is too big for sync download.
32+
Please use async one (ElixirLokaliseApi.Files.download_async/2) instead.
33+
""")
34+
end
35+
36+
{:ok, result}
37+
38+
other ->
39+
other
40+
end
2841
end
2942

3043
@doc """

lib/elixir_lokalise_api/processor.ex

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ defmodule ElixirLokaliseApi.Processor do
3939

4040
case json do
4141
raw_data when type == :raw and status < 400 ->
42-
{:ok, raw_data}
42+
{:ok, create_raw(raw_data, response.headers)}
4343

4444
data when type == :foreign_model and status < 400 ->
4545
{:ok, create_struct(:foreign_model, module, data)}
@@ -60,6 +60,13 @@ defmodule ElixirLokaliseApi.Processor do
6060
end
6161
end
6262

63+
defp create_raw(raw_data, headers) do
64+
case get_header(headers, "x-response-too-big") do
65+
[] -> raw_data
66+
_ -> Map.put(raw_data, :_request_too_big, true)
67+
end
68+
end
69+
6370
defp create_struct(:foreign_model, module, raw_data) do
6471
foreign_model = module.foreign_model()
6572

@@ -102,8 +109,8 @@ defmodule ElixirLokaliseApi.Processor do
102109
[] ->
103110
acc
104111

105-
[list | _] ->
106-
header_value = list |> elem(1)
112+
[header_pair | _] ->
113+
header_value = header_pair |> elem(1)
107114

108115
parsed_value =
109116
case Integer.parse(header_value) do

mix.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ defmodule ElixirLokaliseApi.MixProject do
22
use Mix.Project
33

44
@source_url "https://github.com/lokalise/elixir-lokalise-api"
5-
@version "3.6.0"
5+
@version "3.6.1"
66

77
def project do
88
[

mix.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"dialyxir": {:hex, :dialyxir, "1.4.5", "ca1571ac18e0f88d4ab245f0b60fa31ff1b12cbae2b11bd25d207f865e8ae78a", [:mix], [{:erlex, ">= 0.2.7", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "b0fb08bb8107c750db5c0b324fa2df5ceaa0f9307690ee3c1f6ba5b9eb5d35c3"},
66
"earmark_parser": {:hex, :earmark_parser, "1.4.44", "f20830dd6b5c77afe2b063777ddbbff09f9759396500cdbe7523efd58d7a339c", [:mix], [], "hexpm", "4778ac752b4701a5599215f7030989c989ffdc4f6df457c5f36938cc2d2a2750"},
77
"erlex": {:hex, :erlex, "0.2.7", "810e8725f96ab74d17aac676e748627a07bc87eb950d2b83acd29dc047a30595", [:mix], [], "hexpm", "3ed95f79d1a844c3f6bf0cea61e0d5612a42ce56da9c03f01df538685365efb0"},
8-
"ex_doc": {:hex, :ex_doc, "0.37.3", "f7816881a443cd77872b7d6118e8a55f547f49903aef8747dbcb345a75b462f9", [:mix], [{:earmark_parser, "~> 1.4.42", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "e6aebca7156e7c29b5da4daa17f6361205b2ae5f26e5c7d8ca0d3f7e18972233"},
8+
"ex_doc": {:hex, :ex_doc, "0.38.1", "bae0a0bd5b5925b1caef4987e3470902d072d03347114ffe03a55dbe206dd4c2", [:mix], [{:earmark_parser, "~> 1.4.44", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "754636236d191b895e1e4de2ebb504c057fe1995fdfdd92e9d75c4b05633008b"},
99
"excoveralls": {:hex, :excoveralls, "0.18.5", "e229d0a65982613332ec30f07940038fe451a2e5b29bce2a5022165f0c9b157e", [:mix], [{:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "523fe8a15603f86d64852aab2abe8ddbd78e68579c8525ae765facc5eae01562"},
1010
"exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm", "32e95820a97cffea67830e91514a2ad53b888850442d6d395f53a1ac60c82e07"},
1111
"exvcr": {:hex, :exvcr, "0.17.1", "3bae83d698a464a48212ad87c8ea4bcfb6bd76d53b937129472764e557616228", [:mix], [{:exjsx, "~> 4.0", [hex: :exjsx, repo: "hexpm", optional: false]}, {:finch, "~> 0.16", [hex: :finch, repo: "hexpm", optional: true]}, {:httpoison, "~> 1.0 or ~> 2.0", [hex: :httpoison, repo: "hexpm", optional: true]}, {:ibrowse, "~> 4.4", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:meck, "~> 1.0", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm", "a39d86980da183011366a878972e0ed43a5441814b701edd2e11360564e7bcab"},

test/elixir_lokalise_api/endpoints/files_test.exs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import ExUnit.CaptureIO
2+
13
defmodule ElixirLokaliseApi.FilesTest do
24
use ExUnit.Case, async: true
35
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
@@ -82,6 +84,42 @@ defmodule ElixirLokaliseApi.FilesTest do
8284
end
8385
end
8486

87+
test "downloads files with too big response" do
88+
use_cassette "files_download_response_too_big" do
89+
data = %{
90+
format: "json",
91+
original_filenames: true
92+
}
93+
94+
warning =
95+
capture_io(:stderr, fn ->
96+
{:ok, %{} = resp} = Files.download(@project_id, data)
97+
assert String.contains?(resp.bundle_url, "Demo_Phoenix")
98+
assert resp.project_id == @project_id
99+
assert resp._request_too_big
100+
end)
101+
102+
assert warning =~ "Your project is too big for sync download"
103+
end
104+
end
105+
106+
test "downloads file (error)" do
107+
use_cassette "files_download_error" do
108+
data = %{
109+
format: "json",
110+
original_filenames: true
111+
}
112+
113+
{:error, resp} = Files.download(@project_id, data)
114+
115+
{msg_data, code} = resp
116+
message = msg_data.error.message
117+
118+
assert code == 500
119+
assert message == "Fail"
120+
end
121+
end
122+
85123
test "downloads files asynchronously" do
86124
process_id = "1efed526-cd7c-6f2e-9db9-360c3c31288f"
87125
project_id = "6504960967ab53d45e0ed7.15877499"
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
[
2+
{
3+
"request": {
4+
"body": "{\"format\":\"json\",\"original_filenames\":true}",
5+
"headers": {
6+
"X-Api-Token": "***",
7+
"Accept": "application/json",
8+
"User-Agent": "elixir-lokalise-api package/3.5.0"
9+
},
10+
"method": "post",
11+
"options": [],
12+
"request_body": "",
13+
"url": "https://api.lokalise.com/api2/projects/803826145ba90b42d5d860.46800099/files/download"
14+
},
15+
"response": {
16+
"binary": false,
17+
"body": "{\"error\":{\"message\":\"Fail\",\"code\":500}}",
18+
"headers": {
19+
"Server": "nginx",
20+
"Content-Type": "application/json",
21+
"Transfer-Encoding": "chunked",
22+
"Connection": "keep-alive",
23+
"Vary": "Accept-Encoding",
24+
"Cache-Control": "max-age=0, must-revalidate, no-cache, no-store, private",
25+
"Date": "Tue, 09 Mar 2021 15:30:44 GMT",
26+
"Pragma": "no-cache",
27+
"X-Content-Type-Options": "nosniff",
28+
"X-Frame-Options": "deny",
29+
"X-XSS-Protection": "1; mode=block",
30+
"Strict-Transport-Security": "max-age=31536000",
31+
"Referrer-Policy": "origin",
32+
"Expires": "Tue, 09 Mar 2021 15:30:44 GMT",
33+
"Access-Control-Allow-Origin": "*",
34+
"Access-Control-Allow-Headers": "Content-Type"
35+
},
36+
"status_code": 500
37+
}
38+
}
39+
]
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
[
2+
{
3+
"request": {
4+
"body": "{\"format\":\"json\",\"original_filenames\":true}",
5+
"headers": {
6+
"X-Api-Token": "***",
7+
"Accept": "application/json",
8+
"User-Agent": "elixir-lokalise-api package/3.5.0"
9+
},
10+
"method": "post",
11+
"options": [],
12+
"request_body": "",
13+
"url": "https://api.lokalise.com/api2/projects/803826145ba90b42d5d860.46800099/files/download"
14+
},
15+
"response": {
16+
"binary": false,
17+
"body": "{\"project_id\":\"803826145ba90b42d5d860.46800099\",\"branch\":\"master\",\"bundle_url\":\"https:\\/\\/s3-eu-west-1.amazonaws.com\\/lokalise-assets\\/files\\/export\\/803826145ba90b42d5d860.46800099\\/dd272dd041482e636bdc30142a8944b6\\/Demo_Phoenix-locale.zip\"}",
18+
"headers": {
19+
"Server": "nginx",
20+
"Content-Type": "application/json",
21+
"Transfer-Encoding": "chunked",
22+
"Connection": "keep-alive",
23+
"Vary": "Accept-Encoding",
24+
"Cache-Control": "max-age=0, must-revalidate, no-cache, no-store, private",
25+
"Date": "Tue, 09 Mar 2021 15:30:44 GMT",
26+
"Pragma": "no-cache",
27+
"X-Content-Type-Options": "nosniff",
28+
"X-Frame-Options": "deny",
29+
"X-XSS-Protection": "1; mode=block",
30+
"X-Response-Too-Big": "true",
31+
"Strict-Transport-Security": "max-age=31536000",
32+
"Referrer-Policy": "origin",
33+
"Expires": "Tue, 09 Mar 2021 15:30:44 GMT",
34+
"Access-Control-Allow-Origin": "*",
35+
"Access-Control-Allow-Headers": "Content-Type"
36+
},
37+
"status_code": 200,
38+
"type": "ok"
39+
}
40+
}
41+
]

0 commit comments

Comments
 (0)