Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTTPoison.AsyncResponse id's can be {:maybe_redirect_response, status, headers, client} #424

Merged
merged 2 commits into from
Oct 17, 2020

Conversation

vereis
Copy link
Contributor

@vereis vereis commented Oct 7, 2020

I ran into the following situation working with a script.google.com/... API:

POST-ing to a URL which returned a 302 meant that redirection was not followed because :hackney will only follow redirects if a POST request status was 304, but if follow_redirects: true is given as a request option, HTTPoison returns: {:ok, %HTTPoison.AsyncResponse{id: {:maybe_redirect, ..., ..., ...}}

Passing hackney: [force_redirects: true] to the request to try to circumvent this does not work as expected, because :hackney doesn't follow the spec and change the method to GET, causing the request to return a 405.

For my use case, handling the error is perfectly fine, but unfortunately dialyzer complains about the following match because the HTTPoison.AsyncResponse's id is not a reference but instead just a tuple probably bubbling up from :hackney:

    case HTTPoison.post(@url, params, [], follow_redirect: true) do
      {:ok, %HTTPoison.AsyncResponse{id: {:maybe_redirect, 302, headers, _}}} ->
        Logger.warning(...)
        :ok

      ... ->
    end

Not sure if this was known behaviour, but if so I've amended the type spec in this MR although perhaps one should return a different struct altogether?

@edgurgel
Copy link
Owner

edgurgel commented Oct 8, 2020

@vereis Thanks for the very detailed explanation 🏆

I agree that the result is a bit weird given that the id is a tuple 🤔 I would consider this a bug tbh...

Maybe the best solution is to return a different struct as you suggested? What do you think?

@vereis
Copy link
Contributor Author

vereis commented Oct 8, 2020

Yeah that sounds better, I just didn't want to do too much out of nowhere, but yeah this seems more like a bug! Maybe I should have created an issue first 😅

I think we can just handle where this gets returned and check if it looks like a :maybe_redirect, perhaps return something like {:ok, %HTTPoison.MaybeRedirect{...}} or an error? I'm not sure what you'd prefer in this case to be honest:

If we go with something like {:ok, %HTTPoison.MaybeRedirect{}} I guess we can return the location in this struct, but it'd be up to the user to manually try GET-ing this.

Perhaps since manual intervention is required this is moreso an {:error, %HTTPoison.MaybeRedirect{}} instead? What do you think?

If we wanted to handle this explicitly we could perhaps also add a function HTTPoison.follow_redirect(%HTTPoison.MaybeRedirect{}) which would perform the GET for you, keeping the headers of the original request?

@edgurgel
Copy link
Owner

edgurgel commented Oct 9, 2020

If we go with something like {:ok, %HTTPoison.MaybeRedirect{}} I guess we can return the location in this struct, but it'd be up to the user to manually try GET-ing this.

I like this. Most people won't need to worry as it's not super easy to get to this case?

If we wanted to handle this explicitly we could perhaps also add a function HTTPoison.follow_redirect(%HTTPoison.MaybeRedirect{}) which would perform the GET for you, keeping the headers of the original request?

Maybe we could wait for more feedback once we release the new struct?

What do you think?

@vereis
Copy link
Contributor Author

vereis commented Oct 9, 2020

I like this. Most people won't need to worry as it's not super easy to get to this case?

Yeah exactly, this makes sense to me. I'll give it a shot and update this MR. Thanks for clarifying 💪

@edgurgel
Copy link
Owner

Nice one! I intend to release a new version soon. Cheers! 🎉

@Nitrino
Copy link

Nitrino commented Jan 11, 2021

@edgurgel Can you please release a new version with these changes?

@edgurgel
Copy link
Owner

Yes! Absolutely! I completely forgot about this! 🤦 I will do it later today!

gianluca-nitti pushed a commit to gianluca-nitti/tus_client that referenced this pull request Jan 26, 2022
Updating HTTPoison to 1.8 which includes edgurgel/httpoison#424,
implementing proper handling of redirects. However, WIP because:
- edgurgel/httpoison#453
- need to investigate whether the same (handling
  %HTTPoison.MaybeRedirect{} results) is needed for other requests
  (e.g. options)
gianluca-nitti pushed a commit to gianluca-nitti/tus_client that referenced this pull request Jan 26, 2022
Updating HTTPoison to 1.8 which includes edgurgel/httpoison#424,
implementing proper handling of redirects. However, WIP because:
- edgurgel/httpoison#453
- need to investigate whether the same (handling
  %HTTPoison.MaybeRedirect{} results) is needed for other requests
  (e.g. options)
gianluca-nitti pushed a commit to gianluca-nitti/tus_client that referenced this pull request Feb 1, 2022
Updated HTTPoison to 1.8 which includes edgurgel/httpoison#424,
implementing proper handling of redirects. Additionally, we now
follow redirects for all HTTP methods (not just PATCH).

NOTES (in order of importance):
- POST requests which receive a 303 respose are followed internally by
  HTTPoison but with the GET method, thus if the server replies 303 to a
  POST request the tus upload will not work properly
- there is no redirect loop detection, it may make sense to add an
  option (with a default) to limit the max number of redirects
- edgurgel/httpoison#453 is manually worked around
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants