Recently I once again stumbled upon a detail of the HTTP specification involving the POST verb and "enforced" https. I'll document it here in an attempt to save other people the time (hopefully also future-me).
<span id="more-4486"></span>
I put "enforced" in quotation marks because it just means to also listen on port `80` - apart from listing on port `443` for the encrypted traffic - and issue a redirect (`301`) to the same URL but with `https` instead of `http` as protocol. The thing is that different clients handle that redirect differently and especially the Python `requests` library may confuse you - at least it did confuse me: Say you send a `POST` request to a `http` URL and the server issues a HTTP response code of `301`. According to Wikipedia, the client should confirm with the user before redirecting ((https://en.wikipedia.org/wiki/HTTP_301)). But on the command line or - even worse - in case of libraries used for programming, this is not (easily) possible.
The situation is even more involved if one uses the HTTP status code `302` (which one should *not* do for enforcing https btw): In these cases some - but not all - clients translate a `POST` request to a `GET` request and use that verb against the redirection target ((https://en.wikipedia.org/wiki/HTTP_301)). The two HTTP status codes `303` and `307` have been introduces to deconflict this but all participants need to be backwards-compatible of course.
Anyhow, let's use your favorite CL tool
```bash
curl -v -L -X POST 'http://example.com' > /dev/null
wget -O- --method=POST 'http://example.com' > /dev/null
```
or the Python `requests` library to perform a `POST` request:
```python
import requests
requests.post('http://example.com')
```
All three tools don't interact with the user in any way. They especially re-perform a `POST` in case of `301` without asking first which seems to me like a straight violation of the specification. I cut `requests` some slack of course: As a library it should not wait for user-input during execution.
Tool | 301 redirect | 302 redirect
-----------|--------------|----------------
`curl` | keep `POST` | keep `POST`
`wget` | keep `POST` | switch to `GET`
`requests` | keep `POST` | switch to `GET`