Follow redirects
Follow a redirect with curl -L. Without it curl returns the empty body of the 301, and with it a POST is quietly replaced by a GET on the new address.
A URL that you know works returns nothing in curl, because the server answered with a redirect and curl stopped at it.
curl -si http://127.0.0.1:8000/old | sed -n '1p;/^Location/p'
echo ---
curl -sL http://127.0.0.1:8000/old | head -1
curl -sL -o /dev/null -w '%{url_effective} after %{num_redirects} redirect\n' http://127.0.0.1:8000/old
echo ---
curl -sL -d x=1 http://127.0.0.1:8000/old | head -1HTTP/1.0 301 Moved Permanently
Location: /new
---
GET /new
http://127.0.0.1:8000/new after 1 redirect
---
GET /newRedirects are ordinary responses with a Location header, and curl follows them only when -L is given, as the curl manual says. The -w variables url_effective and num_redirects report where it ended up. The server used here answers /old with a 301 and /new with a copy of the request it received, so the last line shows that the POST arrived as a GET: for 301, 302 and 303 curl switches the method and drops the body.
Add --post301 or --post302 to keep the POST, or use a 307 or 308 on the server, which always preserve it. curl stops after 50 redirects, and --max-redirs lowers that. Credentials given with -u are not sent to a different host after a redirect unless --location-trusted is added, which is the right default.