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

Redirect changes HTTP method to GET #1719

Closed
Lythenas opened this issue Jul 4, 2023 · 2 comments · Fixed by #1744
Closed

Redirect changes HTTP method to GET #1719

Lythenas opened this issue Jul 4, 2023 · 2 comments · Fixed by #1744
Labels
bug Something isn't working
Milestone

Comments

@Lythenas
Copy link
Contributor

Lythenas commented Jul 4, 2023

What is the current bug behavior?

When using hurl --location and there is a redirect on a POST request it will run the (redirected) request as a GET. I suspect this is the same for all HTTP methods, but I haven't checked.

Steps to reproduce

  1. Have an API that redirects a POST request. I am working with an API that redirect all requests from /x to /x/. This is the default for Flask (unsure if it can be changed easily).
  2. echo POST https://localhost/x > test.hurl
  3. hurl --location --verbose test.hurl
  4. See that the POST request gets redirected to https://localhost/x/ and executed as a GET request

What is the expected correct behavior?

The redirected request should use the same HTTP method as the original request.

Execution context

  • Hurl Version (hurl --version): hurl 4.0.0
  • Operating system and version: Ubuntu 22.04

Possible fixes

If it is desired to change the behavior I can look into making a PR.

@Lythenas Lythenas added the bug Something isn't working label Jul 4, 2023
@jcamiel
Copy link
Collaborator

jcamiel commented Jul 4, 2023

Hi @Lythenas thank you for the issue, I wasn't aware of it, I was thinking that a redirection always switch to a GET.
We should follow curl's behaviour:

Text Permanent Temporary
Switch to GET 301 302 and 303
Keep original method 308 307

And in the curl man:

When curl follows a redirect and if the request is a POST, it will send the following request with a GET if the HTTP
response was 301, 302, or 303. If the response code was any other 3xx code, curl will re-send the following request
using the same unmodified method.

There are also --post301, --post302 and --post303 options from curl that we could implement later to alter the redirection behaviour.

You're welcome to contribute if you want (there is a CONTRIBUTING.md guide). In any case, the issue is in our backlog!

@Lythenas
Copy link
Contributor Author

Lythenas commented Jul 4, 2023

Just dumping information here for later use:

According to the source code I found, Flask will use a 308 (https://github.com/pallets/werkzeug/blob/4048509fb24196df67f944a24aaa4ce1afcba92f/src/werkzeug/routing/exceptions.py#L34) so implementing what curl does would be fine for me.

This is the official HTTP standard: https://datatracker.ietf.org/doc/html/rfc9110#name-301-moved-permanently

Note: For historical reasons, a user agent MAY change the request method from POST to GET for the subsequent request. If this behavior is undesired, the 308 (Permanent Redirect) status code can be used instead.

Similar for 302, 303 is meant to always redirect to GET or HEAD.

Implementing the same behavior as curl is probably the best approach. And with the flags the user can then choose to do what they want anyway.

I would maybe be inclined to add an additional flag (not sure what to call it, maybe --location-get-only or --location=get-only) that only redirects on GET and HEAD and has the same behavior as no --location on all other methods.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants