Skip to content

Commit

Permalink
Merge pull request #55 from amatalai/follow-redirects-improvement
Browse files Browse the repository at this point in the history
Follow redirects improvement
  • Loading branch information
teamon authored Feb 6, 2017
2 parents 8201543 + 767b054 commit 74f3aa5
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 7 deletions.
21 changes: 14 additions & 7 deletions lib/tesla/middleware/follow_redirects.ex
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
defmodule Tesla.Middleware.FollowRedirects do
@doc """
@moduledoc """
Follow 301/302 redirects
Example:
defmodule MyClient do
use Tesla
defmodule MyClient do
use Tesla
plug Tesla.Middleware.FollowRedirects, max_redirects: 3 # defaults to 5
end
plug Tesla.Middleware.FollowRedirects, max_redirects: 3 # defaults to 5
end
**NOTE** For `httpc` adapter you have to explicitely disable default autoredirection
adapter :httpc, autoredirect: false
"""
@max_redirects 5
@redirect_statuses [301, 302, 307, 308]
Expand All @@ -19,8 +21,13 @@ defmodule Tesla.Middleware.FollowRedirects do
redirect(env, next, max)
end

defp redirect(_env, _next, left) when left <= 0 do
raise Tesla.Error, "too many redirects"
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
_ ->
raise Tesla.Error, "too many redirects"
end
end

defp redirect(env, next, left) do
Expand Down
60 changes: 60 additions & 0 deletions test/tesla/middleware/follow_redirects_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
defmodule FollowRedirectsTest do
use ExUnit.Case

use Tesla.Middleware.TestCase, middleware: Tesla.Middleware.FollowRedirects

defmodule Client do
use Tesla

plug Tesla.Middleware.FollowRedirects

adapter fn (env) ->
{status, headers, body} = case env.url do
"/0" ->
{200, %{'Content-Type' => 'text/plain'}, "foo bar"}
"/" <> n ->
next = String.to_integer(n) - 1
{301, %{'Location' => '/#{next}'}, ""}
end

%{env | status: status, headers: headers, body: body}
end
end

test "redirects if default max redirects isn't exceeded" do
assert Client.get("/5").status == 200
end

test "raise error when redirect default max redirects is exceeded" do
assert_raise(Tesla.Error, "too many redirects", fn-> Client.get("/6") end)
end

defmodule CustomMaxRedirectsClient do
use Tesla

plug Tesla.Middleware.FollowRedirects, max_redirects: 1

adapter fn (env) ->
{status, headers, body} = case env.url do
"/0" ->
{200, %{'Content-Type' => 'text/plain'}, "foo bar"}
"/" <> n ->
next = String.to_integer(n) - 1
{301, %{'Location' => '/#{next}'}, ""}
end

%{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("/1").status == 200
end

test "raise error when custom max redirects is exceeded" do
assert_raise(Tesla.Error, "too many redirects", fn-> CMRClient.get("/2") end)
end

end

0 comments on commit 74f3aa5

Please sign in to comment.