Posting POST, getting GET



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). 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[1]. 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[2]. 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
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:
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
  1. https://en.wikipedia.org/wiki/HTTP_301 [back]
  2. https://en.wikipedia.org/wiki/HTTP_301 [back]

Leave a Reply

Your email address will not be published. Required fields are marked *