Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F113295
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
3 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 c5ca76a..61b9d06 100644
--- a/lib/tesla/middleware/follow_redirects.ex
+++ b/lib/tesla/middleware/follow_redirects.ex
@@ -1,95 +1,100 @@
defmodule Tesla.Middleware.FollowRedirects do
@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`)
"""
@behaviour Tesla.Middleware
@max_redirects 5
@redirect_statuses [301, 302, 303, 307, 308]
@impl Tesla.Middleware
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
{:ok, %{status: status} = env} when not (status in @redirect_statuses) ->
{:ok, env}
{:ok, _env} ->
{:error, {__MODULE__, :too_many_redirects}}
error ->
error
end
end
defp redirect(env, next, left) do
case Tesla.run(env, next) do
{:ok, %{status: status} = res} when status in @redirect_statuses ->
case Tesla.get_header(res, "location") do
nil ->
{:ok, res}
location ->
prev_uri = URI.parse(env.url)
next_uri = parse_location(location, res)
+ # Copy opts and query params from the response env,
+ # these are not modified in the adapters, but middlewares
+ # that come after might store state there
+ env = %{env | opts: res.opts}
+
env
|> filter_headers(prev_uri, next_uri)
|> new_request(status, URI.to_string(next_uri))
|> redirect(next, left - 1)
end
other ->
other
end
end
# The 303 (See Other) redirect was added in HTTP/1.1 to indicate that the originally
# requested resource is not available, however a related resource (or another redirect)
# available via GET is available at the specified location.
# https://tools.ietf.org/html/rfc7231#section-6.4.4
defp new_request(env, 303, location), do: %{env | url: location, method: :get, query: []}
# The 307 (Temporary Redirect) status code indicates that the target
# resource resides temporarily under a different URI and the user agent
# MUST NOT change the request method (...)
# https://tools.ietf.org/html/rfc7231#section-6.4.7
defp new_request(env, 307, location), do: %{env | url: location}
defp new_request(env, _, location), do: %{env | url: location, query: []}
defp parse_location("https://" <> _rest = location, _env), do: URI.parse(location)
defp parse_location("http://" <> _rest = location, _env), do: URI.parse(location)
defp parse_location(location, env), do: env.url |> URI.parse() |> URI.merge(location)
# See https://github.com/teamon/tesla/issues/362
# See https://github.com/teamon/tesla/issues/360
@filter_headers ["authorization", "host"]
defp filter_headers(env, prev, next) do
if next.host != prev.host || next.port != prev.port || next.scheme != prev.scheme do
%{env | headers: Enum.filter(env.headers, fn {k, _} -> k not in @filter_headers end)}
else
env
end
end
end
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Nov 25, 1:32 AM (1 d, 7 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
39533
Default Alt Text
(3 KB)
Attached To
Mode
R28 tesla
Attached
Detach File
Event Timeline
Log In to Comment