A request method is a promise about side effects, not just a verb you pass to a client. When the origin is a static file tree, most of that promise is already settled before the first request: the tree has no transactions, so methods that would mutate state have nothing safe to mutate.

The method is part of the contract

HTTP method semantics are defined in RFC 9110. GET and HEAD must be safe: they promise a client that the request does not change server state. PUT, POST, and DELETE are not safe by default; they may change state. A server that cannot honor the promise should say so with an explicit status, not with a guessed body.

For a static site the useful distinctions are:

  • GET returns the representation.
  • HEAD returns the same response metadata without the body.
  • OPTIONS discloses what the origin will accept.
  • POST / PUT / DELETE / PATCH have no meaning for an immutable file tree and should be rejected.

What a Caddy static origin actually answers

Point curl at the public edge and the method boundary is easy to read. An OPTIONS request against a site that only serves files returns 405 Method Not Allowed:

$ curl -s -o /dev/null -w 'OPTIONS -> HTTP %{http_code}\n' -X OPTIONS https://www.xbcatm.com/
OPTIONS -> HTTP 405

A 405 with an Allow header naming the supported methods is the correct, explicit reject. Compare this with a dynamic origin that happens to ignore the body: an imported handler can turn a universal non-promise into silent success, which hides the actual contract.

HEAD should equal GET except for the body

Because HEAD is safe and body-free, its metadata should match the equivalent GET. Content-Length still describes the bytes a GET would return. On this site both agree:

HEAD content-length: 15890
GET  bytes read     : 15890

If a proxy strips or rewrites Content-Length on HEAD, a checker that compares the two will catch it. This is the parity the head-request-parity note and the check-http-headers.sh helper both rely on.

What to do when a client sends a mutating method

Answer explicitly. Return 405 Method Not Allowed with an Allow header listing the safe methods, rather than falling through to a page that looks successful. The HTTP foundations path depends on a single obvious answer at the edge: every method is either supported with its documented semantics or rejected with a status that says so.

Sources