An HTTP status is part of the interface. A browser may render a friendly page, but a monitor, crawler, cache, and API client also need the status code and headers to tell the same story.

An old endpoint receives POST and returns 308 with Location; after resolving Location the client can send POST to the new endpoint. 307 and 308 preserve method while 301 and 302 may change POST to GET. Separate absence branches show 404 for temporary or unknown absence and 410 for likely permanent unavailability; neither explains the cause and a friendly page must retain the correct non-200 status. Relative Location is valid when resolved against the original URI. 308 caching depends on method and cache controls; a cached move can outlast configuration. Curl without --location does not follow.
Choose relocation or absence deliberately. Preserve the required method, resolve Location, account for caching, and keep error-page status truthful.

Permanent moves are not all interchangeable

308 Permanent Redirect communicates that the resource has a new permanent URI while preserving the request method. That is important for a client that sends POST, PUT, or another non-GET method. A redirect from an old page to a new page is easy to test with GET; a migration of an endpoint must also be tested with the method that real callers use.

curl -sS -D - -o /dev/null https://old.example.test/api/item

Without --location, curl leaves the redirect unfollowed. Resolve Location against the original URI: an absolute URI, root-relative path, or other relative reference can be valid. Check the resolved host, path, and scheme. 301/302 permit changing POST to GET; 307/308 preserve the method. Test state-changing methods only against an isolated endpoint. 308 is heuristically cacheable, subject to method and cache controls, so a cached move can outlive a server configuration change.

If the intent is to show a result after a completed action, 303 See Other points to a separate resource that the client can retrieve with GET or HEAD. It does not ask the client to replay the original write at a new address; choose that behavior deliberately rather than treating every redirect as a relocation.

Distinguish missing from removed

Use 404 Not Found when the server cannot find a current representation and the absence may be temporary or unknown. 410 Gone is stronger: it says access is no longer available and the condition is likely permanent; it does not establish why the resource disappeared. Both should have a body that helps a human, but neither should return 200 just because a custom error page rendered successfully.

404 can also conceal whether a forbidden resource exists. Both 404 and 410 are heuristically cacheable, subject to method and cache controls. Choose an explicit policy for error responses: a cached missing-route result can remain visible after the route is repaired.

The check belongs at the edge:

curl -sS -D missing.headers -o missing.html -w '%{http_code} %{url_effective}\n' \
  https://www.example.test/a-route-that-does-not-exist

Keep the response headers on the error path. Security headers, a useful content type, and a correct status are more valuable than a decorative error animation.

Sources