I was working on a new project recently where I built both a frontend and a backend. I noticed a weird behaviour where one of my fetch requests would not succeed. It was a request that was trying to patch a resource. Weirdly enough, this request would fail the CORS preflight check and therefore be rejected by the browser. I looked at it and could not see any obvious problem on the server side. I had another request already that was patching a resource which would work just fine. I compared them and found only one difference. One was using {method: 'PATCH'} whereas the other was using {method: 'patch'}. I could not imagine that this was the problem as it worked fine for POST requests written as {method: 'post'}. I created the following minimal example to reproduce this case:

const body = JSON.stringify({foo: 'bar'});

const postUppercase = () => {
  fetch('https://httpbin.org/post', {body, method: 'POST'})
    .then(console.log);  // ✅ Success 
const postLowercase = () => {
  fetch('https://httpbin.org/post', {body, method: 'post'})
    .then(console.log);  // ✅ Success

const patchUppercase = () => {
  fetch('https://httpbin.org/patch', {body, method: 'PATCH'})
    .then(console.log); // ✅ Success
const patchLowercase = () => {
  fetch('https://httpbin.org/patch', {body, method: 'patch'})
    .then(console.log); // ⚠️Error: Method patch is not allowed by Access-Control-Allow-Methods.

My original test was even bigger and validated that for all other standard http verbs - POST, PUT, GET, DELETE, HEAD - it would not matter if I wrote them in all uppercase, all lowercase or even mixed case. Together with Jannis I looked at the WHATWG standard and found a relevant section that could explain this. In there, the standard says the following about how to handle method names:

To normalize a method, if it is a byte-case-insensitive match for DELETE, GET, HEAD, OPTIONS, POST, or PUT, byte-uppercase it.

PATCH is not one of the methods and the spec even points out that patch will likely be rejected by the server with a HTTP 405 response (method not allowed). Why exactly PATCH is not uppercased I don’t really understand but according to a github discussion the current uppercase-conversion only happens for backwards compability. There was the idea of adding a warning every time the browser would uppercase a method name to raise developer awareness that technically they should always uppercase their method names but this discussion was later dropped.

The takeaway from all of this: HTTP verbs are always uppercase. Some clients might allow you to write them in lowercase and convert them to uppercase for you (see axios - where technically this now blocks users from making an elaborate paTch request if they think this would be necessary) or you might use one of the standard verbs which get capitalized according the spec but you are probably better of, just writing all method names in all caps all the time. Happy PATCHing!