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

🐛 Bug Report — Request Throws 'Invalid HTTP method' Error when Using Lowercase Method "patch" #2516

Open
Kynson opened this issue Aug 11, 2024 · 6 comments
Labels
api feature request Request for Workers team to add a feature spec-compliance

Comments

@Kynson
Copy link

Kynson commented Aug 11, 2024

The Issue

new Request('', {method: 'patch'}) unexpectedly throws error 'Invalid HTTP method string: patch' but new Request('', {method: 'PATCH'}) works fine.

Minimal Reproducible Example: Workers Playground

Expected Behaviour

Both lowercase and uppercase method string should be supported (other methods support both lowercase and uppercase).

Suspected Cause

L1000 of workerd/api/http.c++:

switch(method) {
                case kj::HttpMethod::GET:
                case kj::HttpMethod::POST:
                case kj::HttpMethod::PUT:
                case kj::HttpMethod::DELETE:
                case kj::HttpMethod::HEAD:
                case kj::HttpMethod::OPTIONS:
                  break;
                default:
                  JSG_FAIL_REQUIRE(TypeError, kj::str("Invalid HTTP method string: ", originalMethod));
}

Presumably, the switch statement will run when a lowercase method string is passed to the constructor as tryParseHttpMethod failed to parse the lowercase method string. Yet, PATCH is missing from the switch statement, so the error is thrown. I am not particularly familiar with C++ so I might be wrong with this.

@kentonv
Copy link
Member

kentonv commented Aug 12, 2024

@harrishancock I don't suppose you remember why we're only case-insensitive for those six method names? Was this in the spec or something?

@jasnell
Copy link
Member

jasnell commented Aug 12, 2024

If by spec you mean the http spec, there's nothing about special handling casing of only these basic 6 methods. Per the spec, all http methods are case sensitive.

https://www.rfc-editor.org/rfc/rfc7231#section-4

The method token is case-sensitive because it might be used as a gateway to object-based systems with case-sensitive method names.

So we really ought to be treating get, post, put, delete, head, and options as invalid also.

For the original ask here, PATCH is correct. patch is incorrect.

@jasnell
Copy link
Member

jasnell commented Aug 12, 2024

Testing chromium, it does appear that chromium's implementation will automatically convert get to GET but won't convert patch to PATCH... and yeah, this appears to be part of the fetch standard https://fetch.spec.whatwg.org/#methods

image

It even calls out patch vs PATCH explicitly.

So it would appear that our implemented behavior is correct per the fetch spec and accordingly bends a rule of the HTTP RFC to special case these six methods. Good fun.

Quick test across run times for console.log((new Request('http://example.org', { method: 'patch' }).method)

  • Chromium browsers: patch (per the spec, not uppercased)
  • Node.js: patch (per the spec, not uppercased)
  • Deno: PATCH (does not match spec, uppercased)
  • Bun: PATCH (does not match spec, uppercased)

@kentonv
Copy link
Member

kentonv commented Aug 14, 2024

I guess we're still violating spec either way in that if you specify patch lower-case, we throw an exception, whereas we should accept it. It seems better to uppercase it than to throw an exception I think.

Arguably we should actually expand the underlying KJ HTTP implementation to support arbitrary method names, rather than restricting them to an enum. I'm not excited about doing that, though, as:

  • We've literally never heard anyone complain about wanting to use a method that's not on our list.
  • There's some risk of security (request smuggling) bugs if someone defines a new method which, like CONNECT, doesn't use standard HTTP message framing.

So I'd be in favor of just upper-casing all methods.

@jasnell
Copy link
Member

jasnell commented Aug 14, 2024

We've literally never heard anyone complain about wanting to use a method that's not on our list.

To be fair, they probably wouldn't. If they needed a method that didn't work in workers they're more likely to just not use workers than to complain about it not working

That said, upper-casing all methods is fine as a first step, I think. Likely requires a compat flag tho.

@jasnell jasnell added the feature request Request for Workers team to add a feature label Aug 15, 2024
@jasnell
Copy link
Member

jasnell commented Aug 15, 2024

Marking as a feature request rather than a bug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api feature request Request for Workers team to add a feature spec-compliance
Projects
None yet
Development

No branches or pull requests

3 participants