views:

1902

answers:

4

I can't seem to figure out how to access POST data using WSGI. I tried the example on the wsgi.org website and it didn't work. I'm using Python 3.0 right now. Please don't recommend a WSGI framework as that is not what I'm looking for.

I would like to figure out how to get it into a fieldstorage object.

+1  A: 

I would suggest you look at how some frameworks do it for an example. (I am not recommending any single one, just using them as an example.)

Here is the code from Werkzeug:

http://dev.pocoo.org/projects/werkzeug/browser/werkzeug/wrappers.py#L150

which calls

http://dev.pocoo.org/projects/werkzeug/browser/werkzeug/utils.py#L1420

It's a bit complicated to summarize here, so I won't.

Ali A
Still doesn't work in Python 3.0, and that's what I'm looking for. Thanks anyways, though.
Evan Fosmark
-1 question asked not to be shown frameworks
Fire Crow
+6  A: 
body= ''  # b'' for consistency on Python 3.0
try:
    length= int(environ.get('CONTENT_LENGTH', '0'))
except ValueError:
    length= 0
if length!=0:
    body= environ['wsgi.input'].read(length)

Note that WSGI is not yet fully-specified for Python 3.0, and much of the popular WSGI infrastructure has not been converted (or has been 2to3d, but not properly tested). (Even wsgiref.simple_server won't run.) You're in for a rough time doing WSGI on 3.0 today.

bobince
Yeah I had issues getting wsgiref to work. I ended up implementing the patch.
Evan Fosmark
+3  A: 

Assuming you are trying to get just the POST data into a FieldStorage object:

# env is the environment handed to you by the WSGI server.
# I am removing the query string from the env before passing it to the
# FieldStorage so we only have POST data in there.
post_env = env.copy()
post_env['QUERY_STRING'] = ''
post = cgi.FieldStorage(
    fp=env['wsgi.input'],
    environ=post_env,
    keep_blank_values=True
)
Mike Boers
This doesn't work in Python 3.0 - it has a problem with the wsgi.input returning bytes instead of strings. :( I need a way of doing this in Python 3.0...
Evan Fosmark
What WSGI handler are you using? If I use the built-in CGIHandler it works just fine for me.I have a file "post.cgi" on my local server with the contents at http://pastebin.com/f40849562 running just fine.
Mike Boers
What io class is the wsgi.input? If it is a BufferedIOBase then you should be able to wrap it in a TextIOWrapper so that the cgi.FieldStorage can use it.
Mike Boers
@Mike, I thought of that too, but that would make it not function properly in the long run as post data can be binary (eg, files).
Evan Fosmark
@Evan, Maybe I'm crazy, but you *could* wrap the input in a TextIOWrapper and extend the FieldStorage and override the `make_file` method to return your own wrapper around a file which encodes back to binary data as it writes... If this can't be done an easier way. Which WSGI handler are you using?
Mike Boers
@Mike, I'm just using wsgiref, which on its own took a lot of modification to get working in 3.0.
Evan Fosmark
@Evan: Any particular handler, or the CGIHandler? Cause that one is working just fine for me with 3.0. Maybe I'm not pushing it very hard?
Mike Boers
@Mike, I'm using WSGIServer. I haven't tried it with CGIHandler, but I'd prefer not to ever have to use that since it sort of breaks the point of WSGI in my opinion.
Evan Fosmark
@Evan: Well that is really broken in 3.0, isn't it? I'll play around with it in the near future (cause I am interested in moving to 3.0 for my apps) and post results here.
Mike Boers
@Mike, thank's a lot. :) I'm going to set this as the answer so you get the bounty because you've been so helpful.
Evan Fosmark
A: 

This worked for me (in Python 3.0):

import urllib.parse

post_input = urllib.parse.parse_qs(environ['wsgi.input'].readline().decode(),True)

Jack