How do I get POST "data" variable in python3.x without using CGI?
ajax, cgi, encoding, post, python-3.x
Solution
According to http://lucumr.pocoo.org/2013/7/2/the-updated-guide-to-unicode/:
"There are also some special cases in the stdlib where strings are
very confusing. The cgi.FieldStorage module which WSGI applications are
sometimes still using for form data parsing is now treating QUERY_STRING
as surrogate escaping, but instead of using utf-8 as charset for the URLs
(as browsers) it treats it as the encoding returned by
locale.getpreferredencoding(). I have no idea why it would do that, but
it's incorrect. As workaround I recommend not using cgi.FieldStorage for
query string parsing."
The solution to this problem is to use `sys.stdin.read` to read in POST data parameters. However please note that your cgi application can hang if it expects to read in something and nothing is sent. This is solved by reading in the number of bytes that is found in the HTTP Header:
#!/usr/bin/env python3
import os, sys, json
data = sys.stdin.read(int(os.environ.get('HTTP_CONTENT_LENGTH', 0)))
# To get data in a native python dictionary, use json.loads
if data:
print(list(json.loads(data).keys())) # Prints out keys of json
# (You need to wrap the .keys() in list() because it would otherwise return
# "dict_keys([a, b, c])" instead of [a, b, c])
You can read more about the internals of CGI here: http://oreilly.com/openbook/cgi/ch04_02.html
Problem
When I attempt to call `cgi.FieldStorage()` in a `python3.x` cgi script, I get the following error: ``` [Traceback: error in module x on line y]: cgi.FieldStorage() File "/usr/lib64/python3.3/cgi.py", line 553, in __init__ self.read_single() File "/usr/lib64/python3.3/cgi.py", line 709, in read_single self.read_binary() File "/usr/lib64/python3.3/cgi.py", line 731, in read_binary self.file.write(data) TypeError: must be str, not bytes ``` How do I get my POST `data` variable from an ajax call? Example ajax call: ``` function (param) { $.ajax({ type: "POST", url: "/cgi-bin/mycgi.py/TestMethod", data: JSON.stringify({"foo": "bar"}), contentType: "application/json; charset=utf-8", dataType: "json", success: function (result) { alert("Success " + result); }, error: function () { alert("Failed"); } }); } ```