Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F113229
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
6 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/lib/tesla/middleware/follow_redirects.ex b/lib/tesla/middleware/follow_redirects.ex
index c0c30a3..ba62a9b 100644
--- a/lib/tesla/middleware/follow_redirects.ex
+++ b/lib/tesla/middleware/follow_redirects.ex
@@ -1,64 +1,67 @@
defmodule Tesla.Middleware.FollowRedirects do
@behaviour Tesla.Middleware
@moduledoc """
Follow 3xx redirects
### Example
```
defmodule MyClient do
use Tesla
plug Tesla.Middleware.FollowRedirects, max_redirects: 3 # defaults to 5
end
```
### Options
- `:max_redirects` - limit number of redirects (default: `5`)
"""
@max_redirects 5
@redirect_statuses [301, 302, 307, 308]
def call(env, next, opts \\ []) do
max = Keyword.get(opts || [], :max_redirects, @max_redirects)
redirect(env, next, max)
end
defp redirect(env, next, left) when left == 0 do
case Tesla.run(env, next) do
- %{status: status} = env when not status in @redirect_statuses ->
- env
+ {:ok, %{status: status} = env} when not status in @redirect_statuses ->
+ {:ok, env}
- _ ->
- raise Tesla.Error, "too many redirects"
+ {:ok, env} ->
+ {:error, {__MODULE__, :too_many_redirects}}
+
+ error ->
+ error
end
end
defp redirect(env, next, left) do
case Tesla.run(env, next) do
- %{status: status} = env when status in @redirect_statuses ->
+ {:ok, %{status: status} = env} when status in @redirect_statuses ->
case Tesla.get_header(env, "location") do
nil ->
- env
+ {:ok, env}
location ->
location = parse_location(location, env)
redirect(%{env | url: location}, next, left - 1)
end
- env ->
- env
+ other ->
+ other
end
end
defp parse_location("/" <> _rest = location, env) do
env.url
|> URI.parse()
|> URI.merge(location)
|> URI.to_string()
end
defp parse_location(location, _env), do: location
end
diff --git a/test/tesla/middleware/follow_redirects_test.exs b/test/tesla/middleware/follow_redirects_test.exs
index 9185c00..a1974a3 100644
--- a/test/tesla/middleware/follow_redirects_test.exs
+++ b/test/tesla/middleware/follow_redirects_test.exs
@@ -1,105 +1,108 @@
defmodule Tesla.Middleware.FollowRedirectsTest do
use ExUnit.Case
defmodule Client do
use Tesla
plug Tesla.Middleware.FollowRedirects
adapter fn env ->
{status, headers, body} =
case env.url do
"http://example.com/0" ->
{200, [{"content-type", "text/plain"}], "foo bar"}
"http://example.com/" <> n ->
next = String.to_integer(n) - 1
{301, [{"location", "http://example.com/#{next}"}], ""}
end
- %{env | status: status, headers: headers, body: body}
+ {:ok, %{env | status: status, headers: headers, body: body}}
end
end
test "redirects if default max redirects isn't exceeded" do
- assert Client.get("http://example.com/5").status == 200
+ assert {:ok, env} = Client.get("http://example.com/5")
+ assert env.status == 200
end
test "raise error when redirect default max redirects is exceeded" do
- assert_raise(Tesla.Error, "too many redirects", fn -> Client.get("http://example.com/6") end)
+ assert {:error, {Tesla.Middleware.FollowRedirects, :too_many_redirects}} == Client.get("http://example.com/6")
end
defmodule CustomMaxRedirectsClient do
use Tesla
plug Tesla.Middleware.FollowRedirects, max_redirects: 1
adapter fn env ->
{status, headers, body} =
case env.url do
"http://example.com/0" ->
{200, [{"content-type", "text/plain"}], "foo bar"}
"http://example.com/" <> n ->
next = String.to_integer(n) - 1
{301, [{"location", "http://example.com/#{next}"}], ""}
end
- %{env | status: status, headers: headers, body: body}
+ {:ok, %{env | status: status, headers: headers, body: body}}
end
end
alias CustomMaxRedirectsClient, as: CMRClient
test "redirects if custom max redirects isn't exceeded" do
- assert CMRClient.get("http://example.com/1").status == 200
+ assert {:ok, env} = CMRClient.get("http://example.com/1")
+ assert env.status == 200
end
test "raise error when custom max redirects is exceeded" do
- assert_raise(Tesla.Error, "too many redirects", fn ->
- CMRClient.get("http://example.com/2")
- end)
+ assert {:error, {Tesla.Middleware.FollowRedirects, :too_many_redirects}} == CMRClient.get("http://example.com/2")
end
defmodule RelativeLocationClient do
use Tesla
plug Tesla.Middleware.FollowRedirects
adapter fn env ->
{status, headers, body} =
case env.url do
"https://example.com/pl" ->
{200, [{"content-type", "text/plain"}], "foo bar"}
"http://example.com" ->
{301, [{"location", "https://example.com"}], ""}
"https://example.com" ->
{301, [{"location", "/pl"}], ""}
"https://example.com/" ->
{301, [{"location", "/pl"}], ""}
"https://example.com/article" ->
{301, [{"location", "/pl"}], ""}
end
- %{env | status: status, headers: headers, body: body}
+ {:ok, %{env | status: status, headers: headers, body: body}}
end
end
alias RelativeLocationClient, as: RLClient
test "supports relative address in location header" do
- assert RLClient.get("http://example.com").status == 200
+ assert {:ok, env} = RLClient.get("http://example.com")
+ assert env.status == 200
end
test "doesn't create double slashes inside new url" do
- assert RLClient.get("https://example.com/").url == "https://example.com/pl"
+ assert {:ok, env} = RLClient.get("https://example.com/")
+ assert env.url == "https://example.com/pl"
end
test "rewrites URLs to their root" do
- assert RLClient.get("https://example.com/article").url == "https://example.com/pl"
+ assert {:ok, env} = RLClient.get("https://example.com/article")
+ assert env.url == "https://example.com/pl"
end
end
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Nov 24, 8:09 PM (1 d, 5 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
39483
Default Alt Text
(6 KB)
Attached To
Mode
R28 tesla
Attached
Detach File
Event Timeline
Log In to Comment