ducaale/xh

HTTP method not retained after 301 redirect

yinshanyang opened this issue · 2 comments

I’m not sure if this is expected behaviour, but it seems that the HTTP method is not retained after a 301 redirect.

xh:

> xh --verbose --follow post github.com

POST / HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Host: github.com
User-Agent: xh/0.16.1

HTTP/1.1 301 Moved Permanently
Content-Length: 0
Location: https://github.com/



GET / HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Host: github.com
User-Agent: xh/0.16.1

HTTP/2.0 200 OK
accept-ranges: bytes
cache-control: max-age=0, private, must-revalidate
content-encoding: gzip
content-language: en-US
content-security-policy: default-src 'none'; base-uri 'self'; block-all-mixed-content; child-src github.com/assets-cdn/worker/ gist.github.com/assets-cdn/worker/; connect-src 'self' uploads.github.com objects-origin.githubusercontent.com www.githubstatus.com collector.github.com raw.githubusercontent.com api.github.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com cdn.optimizely.com logx.optimizely.com/v1/events *.actions.githubusercontent.com wss://*.actions.githubusercontent.com online.visualstudio.com/api/v1/locations github-production-repository-image-32fea6.s3.amazonaws.com github-production-release-asset-2e65be.s3.amazonaws.com insights.github.com wss://alive.github.com github.githubassets.com; font-src github.githubassets.com; form-action 'self' github.com gist.github.com objects-origin.githubusercontent.com; frame-ancestors 'none'; frame-src render.githubusercontent.com viewscreen.githubusercontent.com notebooks.githubusercontent.com; img-src 'self' data: github.githubassets.com identicons.github.com github-cloud.s3.amazonaws.com secured-user-images.githubusercontent.com/ github-production-user-asset-6210df.s3.amazonaws.com customer-stories-feed.github.com spotlights-feed.github.com *.githubusercontent.com; manifest-src 'self'; media-src github.com user-images.githubusercontent.com/ secured-user-images.githubusercontent.com/ github.githubassets.com; script-src github.githubassets.com; style-src 'unsafe-inline' github.githubassets.com; worker-src github.com/assets-cdn/worker/ gist.github.com/assets-cdn/worker/
content-type: text/html; charset=utf-8
date: Sat, 20 Aug 2022 07:19:56 GMT
etag: W/"789015f3a87111c1e70fc9c2ed0d47c1"
expect-ct: max-age=2592000, report-uri="https://api.github.com/_private/browser/errors"
permissions-policy: interest-cohort=()
referrer-policy: origin-when-cross-origin, strict-origin-when-cross-origin
server: GitHub.com
set-cookie: _gh_sess=VKyx5r8Z8I8X2qRAieB76GZfMmVNX2WxPSycGb%2BEHDj8L%2FbVoRTjGz3cj%2BrhX24I61xnVyAFKlZa9JZuwkx9c7zI%2BigfyO9SjzlER8CMpXMac9DLBcW1KQOblZBsjB1qRWfXEbU0WHJti%2Fb8t28dExtDhY8iQIQbvoywxh%2FOH9JCuMuiQakOmXDuM0FOpzFxesfxskCp4L2LMyjxukzJ6FexsR1balisPeZA6MnMzhPBXFQE4cWFzntZ84DZd%2BSjSILFC30HribDdxL4bQ4E4g%3D%3D--1CfuV%2BouNRGjyohU--1Z5pmz%2B%2Fmn%2F9xR%2BXKvx1YA%3D%3D; Path=/; HttpOnly; Secure; SameSite=Lax
set-cookie: _octo=GH1.1.1826559704.1660980002; Path=/; Domain=github.com; Expires=Sun, 20 Aug 2023 07:20:02 GMT; Secure; SameSite=Lax
set-cookie: logged_in=no; Path=/; Domain=github.com; Expires=Sun, 20 Aug 2023 07:20:02 GMT; HttpOnly; Secure; SameSite=Lax
strict-transport-security: max-age=31536000; includeSubdomains; preload
vary: X-PJAX, X-PJAX-Container, Turbo-Visit, Turbo-Frame, Accept-Language, Accept-Encoding, Accept, X-Requested-With
x-content-type-options: nosniff
x-frame-options: deny
x-github-request-id: 53FD:6B59:24A4E5:290A32:63008B22
x-xss-protection: 0

… HTML content …

curl:

> curl -L -X POST -v github.com

*   Trying 20.205.243.166:80...
* Connected to github.com (20.205.243.166) port 80 (#0)
> POST / HTTP/1.1
> Host: github.com
> User-Agent: curl/7.79.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 301 Moved Permanently
< Content-Length: 0
< Location: https://github.com/
<
* Connection #0 to host github.com left intact
* Issue another request to this URL: 'https://github.com/'
*   Trying 20.205.243.166:443...
* Connected to github.com (20.205.243.166) port 443 (#1)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*  CAfile: /etc/ssl/cert.pem
*  CApath: none
* (304) (OUT), TLS handshake, Client hello (1):
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-CHACHA20-POLY1305-SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  subject: C=US; ST=California; L=San Francisco; O=GitHub, Inc.; CN=github.com
*  start date: Mar 15 00:00:00 2022 GMT
*  expire date: Mar 15 23:59:59 2023 GMT
*  subjectAltName: host "github.com" matched cert's "github.com"
*  issuer: C=US; O=DigiCert Inc; CN=DigiCert TLS Hybrid ECC SHA384 2020 CA1
*  SSL certificate verify ok.
* Using HTTP2, server supports multiplexing
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x158010a00)
> POST / HTTP/2
> Host: github.com
> user-agent: curl/7.79.1
> accept: */*
>
< HTTP/2 404
< server: GitHub.com
< date: Sat, 20 Aug 2022 07:20:51 GMT
< content-type: text/html; charset=utf-8
< content-length: 0
< strict-transport-security: max-age=31536000; includeSubdomains; preload
< x-frame-options: deny
< x-content-type-options: nosniff
< x-xss-protection: 0
< referrer-policy: origin-when-cross-origin, strict-origin-when-cross-origin
< expect-ct: max-age=2592000, report-uri="https://api.github.com/_private/browser/errors"
< content-security-policy: default-src 'none'; base-uri 'self'; block-all-mixed-content; child-src github.com/assets-cdn/worker/ gist.github.com/assets-cdn/worker/; connect-src 'self' uploads.github.com objects-origin.githubusercontent.com www.githubstatus.com collector.github.com raw.githubusercontent.com api.github.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com cdn.optimizely.com logx.optimizely.com/v1/events; font-src github.githubassets.com; form-action 'self' github.com gist.github.com objects-origin.githubusercontent.com; frame-ancestors 'none'; frame-src render.githubusercontent.com viewscreen.githubusercontent.com notebooks.githubusercontent.com; img-src 'self' data: github.githubassets.com media.githubusercontent.com camo.githubusercontent.com identicons.github.com avatars.githubusercontent.com github-cloud.s3.amazonaws.com objects.githubusercontent.com objects-origin.githubusercontent.com secured-user-images.githubusercontent.com/ github-production-user-asset-6210df.s3.amazonaws.com customer-stories-feed.github.com spotlights-feed.github.com; manifest-src 'self'; media-src github.com user-images.githubusercontent.com/ secured-user-images.githubusercontent.com/; script-src github.githubassets.com; style-src 'unsafe-inline' github.githubassets.com; worker-src github.com/assets-cdn/worker/ gist.github.com/assets-cdn/worker/
< vary: Accept-Encoding, Accept, X-Requested-With
< x-github-request-id: 53A5:22DA:2576AD:29DE20:63008B53
<
* Connection #1 to host github.com left intact

Expected behaviour:

A POST request to http://github.com would result in a 404 response after the redirect.

Environment:

  • Mac Mini M1
  • MacOS 12.5
  • xh version 0.16.1 with native-tls

According to cURL's manpage, 301 HTTP redirections do not retain the HTTP method

When curl follows a redirect and the request is not a plain GET (for example POST or PUT), it will do 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.

However, the use of -X POST is forcing subsequent requests to use POST. To get the same behavior described in the docs, you would want to use -d "" instead. See https://stackoverflow.com/a/41890653/5915221

Note to self: fix xh's curl translation or print a warning when --follow and a method other than GET is used together.

Thanks for the explanation. Closing the issue.