Home / Blog / URL HTTP & cURL

API & webhooks

Fix REST API 405 by Matching the Method to the Resource

Diagnose 405 Method Not Allowed using the actual method, Allow header, route configuration, and CORS preflight before changing a request.

Read the method and destination together

A 405 Method Not Allowed response means the server recognizes the request method but the target resource does not support it. A URL working in the browser's address bar does not establish that the same URL accepts POST, PUT or DELETE. The address-bar navigation normally tests GET, which is a different operation.

The HTTP 405 reference explains that the response should identify supported methods in Allow. Record that header alongside the exact request method and destination. A missing or contradictory Allow value is useful evidence for the service owner, not a reason to guess destructive methods until something succeeds.

Make a small resource's method policy explicit

function notesMethodResponse(method) {
  const allowed = ["GET", "HEAD", "POST"];
  if (!allowed.includes(method)) {
    return Response.json({error: "method_not_allowed"}, {
      status: 405,
      headers: {Allow: allowed.join(", ")}
    });
  }
  if (method === "HEAD") {
    return new Response(null, {
      status: 200,
      headers: {"Content-Type": "application/json"}
    });
  }
  return Response.json({acceptedMethod: method});
}

This example demonstrates method dispatch for one resource. It is not a note creation handler: the POST branch only acknowledges the selected method and does not store data. A real implementation must add the operation's input checks, authorization, storage and appropriate success response before it can claim to create anything.

The HEAD branch returns no body. It supplies the representation's content type for this simplified example; a production implementation should keep applicable response metadata consistent with its corresponding GET behavior. Test the response bytes as well as the status so that a framework does not accidentally attach a JSON body to HEAD.

Separate route selection from request-body validation

Compare the collection route and the item route. A service may accept POST /notes to create a note while allowing PATCH /notes/7 to modify one. Sending POST to the item route can be a method mismatch even when the JSON body is perfectly valid. Read the endpoint contract before editing payload fields.

A 415 response points to a representation-format problem, while 405 concerns the method supported by the target resource. These are different stages of request handling. Changing Content-Type cannot make an unregistered DELETE handler appear, and switching to GET does not correctly implement a write operation.

Check any reverse proxy, static hosting layer or gateway before the application. If the request never reaches the intended handler, changing that handler's code may have no effect. Compare deployment routing rules and trace a controlled request through the component that actually emits the response.

Recognize a failed preflight as a separate request

For some cross-origin browser requests, the browser first sends OPTIONS to check whether the later request is permitted. Inspect the network panel to determine whether the 405 belongs to OPTIONS or to the intended POST. If preflight fails, the browser may never send the application request.

The Allow header and Access-Control-Allow-Methods have different purposes. The former describes methods supported by the resource; the latter participates in the server's CORS policy. Setting either as an arbitrary client request header does not grant browser permission or register a missing server route.

Test supported and unsupported methods deliberately

Use a local fixture or an endpoint you are authorized to test. In the REST API Testing Tool, select the documented method and compare the returned status and browser-exposed Allow header. Do not test DELETE or other writes against production data merely to see whether the server accepts them.

For the example, assert successful GET, bodyless HEAD and a 405 for DELETE with the complete declared method list. Then verify an allowed POST separately. These tests catch a handler that returns 200 for every method or supplies an Allow value that disagrees with its actual dispatch.

After a routing repair, repeat the original failing request without unrelated changes to its body or authentication. A successful response should demonstrate that the intended operation is now supported, rather than showing that the client silently changed to a different operation.