In a CGI Python3 script, how can I read raw form data in POST?

Yes, I know cgi.FieldStorage

, but being some form of an unordered dictionary, it doesn't preserve the order of the original data (see below for proof). Since I want to use this data in the PayPal IPN, it is important to include "PayPal Documents" which says "... you must send back the content in the exact order you received it ..."

Alternatively os.environ.get('QUERY_STRING')

looks perfect, however it only works for GET . Example code: (myscript.py)

#!/usr/bin/python3

import cgi, os

query = os.environ.get('QUERY_STRING') or 'no query'
print ("Content-type: text/plain\n\n")
print("query=" + query)
form = cgi.FieldStorage()
for key in form.keys():
   print("\n" + key + '=' + form.getvalue(key))

      

Works with GET from the browser, for example. (note that foo comes before ggg)

http://example.com/myscript.py/foo=bar&ggg=3&aaa=bbb&zzz=qqq

      

returns

query=foo=bar&ggg=3&aaa=bbb&zzz=qqq
ggg=3
foo=bar   << note that foo now comes after ggg
aaa=bbb
zzz=qqq

      

However, if I use Postman to POST

POST /myscript.py HTTP/1.1
Host: example.com
Cache-Control: no-cache
Content-Type: application/x-www-form-urlencoded

foo=bar&ggg=3&aaa=bbb&zzz=qqq

      

It does not return a query string, and as expected, FormData did not preserve order.

query=no query
ggg=3
foo=bar   << note that foo now comes after ggg
aaa=bbb
zzz=qqq

      

+3


source to share


1 answer


I don't know why no one answered. After a little futzing, I found the solution to be incredibly simple . Is that why no one bothered to answer?

Just read from stdin: (this is Python3 code, not sure if Python2 will be different)

query_string = sys.stdin.read()

There is one drawback: it is incompatible with cgi.FieldStorage()

, since this will also try to read from stdin. So, if you also want a good dictionary to look up query terms, there is one more simple step:



multiform = urllib.parse.parse_qs(query_string)

which, like cgi.FieldStorage, returns multimap , so the name is multiple.

For more details I wrote about it here .

+8


source







All Articles