sfw/fix
301 vs 308 (POST dropped) high

301 redirect drops POST body (use 308)

Clients following a 301/302 often turn POST into GET and drop the body; API and form endpoints need 308 or 307.

What you see

HTTP/1.1 301 Moved Permanently
Location: https://api.example.com/v2/orders

400 Bad Request: missing required field

What’s actually happening

A form submission or API call starts failing right after a URL change. The redirect resolves, but the destination gets an empty GET instead of the POST you sent, so it returns 400/422 for missing fields or just silently does nothing. It looks intermittent because GET endpoints survive the redirect fine while POST/PUT/PATCH/DELETE break. curl -L reproduces it: the method flips to GET on the second request.

Common causes

  • An API or form endpoint was moved (HTTP to HTTPS, host change, trailing-slash normalization) using a 301 or 302.
  • Per RFC, 301/302 allow clients to rewrite the method, and most browsers and many HTTP libraries downgrade POST to GET and discard the body.
  • A trailing-slash or www/non-www redirect sits in front of the API and rewrites POSTs before they reach the handler.
  • Code assumes redirects are transparent and never inspects the method after a Location bounce.
  • A reverse proxy normalizes the path with a default 301 that doesn't preserve the verb.

How to fix it

  1. Use 308 for permanent, 307 for temporary on any non-GET endpoint308 and 307 are defined to keep the original method and body across the redirect (RFC 7538 / RFC 9110). Swap the 301 to 308 (or 302 to 307) wherever POST/PUT/PATCH/DELETE traffic can land.
  2. Verify the method survivesRun curl -L -X POST -d '{"x":1}' -H 'Content-Type: application/json' https://api.example.com/old and confirm the final request is still POST with the body intact. With 301 you'll see it become GET.
  3. Better yet, don't redirect API traffic at allRedirects on hot API paths add a round trip per call. Update clients and SDKs to hit the canonical URL directly, and keep the 308 only as a safety net for stragglers.
  4. Handle the trailing-slash and host normalization explicitlyIf a framework auto-redirects /orders to /orders/ or non-www to www, make that rule a 308 for API routes, or disable strict-slash redirects on the API router so POSTs pass straight through.

Stop it recurring

Reserve 301/302 for pages a browser GETs; use 308/307 on every endpoint that accepts a request body.

Related errors