POST from a CGI

Michael Foord fuzzyman at gmail.com
Wed Sep 22 04:27:42 EDT 2004


I'm receiving POST data to a CGI, which I'd like to forward to another
CGI using urllib2.

I have two options -

1) Parse the data using cgi.FieldStorage() and then rebuild the POST
request into a dictionary - including any files (? uploading files by
urllib2 untested and undocumented - examples seem to be for httplib).

2) Read the whole POST data in using sys.stdin.read(), rebuild the
'Content-type' and 'Content-length' headers and make the POST.

Obviously (2) is a *lot* less fiddly and less error prone. *But* I'm
getting 400 errors when I try it (server thinks request is malformed).
I've checked the headers and the body data and they seem normal and I
can't work it out.

I wonder if anyone can see what I'm doing wrong......
(Simple code shown first - then a straightforward example that ought
to work and fails).

MAXUPLOAD  = 10000                                              # set
max file size of 10 000 bytes
txdata = None
if os.environ.get('REQUEST_METHOD','').lower()=='post':         # read
in the POST data from stdin
    txdata = sys.stdin.read(MAXUPLOAD)
    if len(txdata)==MAXUPLOAD and sys.stdin.read(1):
        print overmax 
        sys.exit(1)                                             #
print an error message if too big a file is uploaded


envdict = { 'HTTP_CACHE_CONTROL' : 'Cache-control', 'CONTENT_TYPE' :
'Content-type',
            'HTTP_ACCEPT_LANGUAGE' : 'Accept-language', 'HTTP_ACCEPT'
: 'Accept',
            'HTTP_PRAGMA' : 'Pragma', 'HTTP_CONNECTION' :
'Connection',
            }                                                   #
these are request headers from the browser to the CGI
                                                                # that
we're going to rebuild from the environment variables
defaultuseragent =  'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'  
        # default User-agent
txheaders = {}
for envvar, header in envdict.items():                  # go through
the environment variables putting any headers back
    testval = os.environ.get(envvar)
    if testval:
        txheaders[header] = testval
txheaders['User-agent'] = os.environ.get('HTTP_USER_AGENT',
defaultuseragent)   # put in a default user agent if we haven't got
one
if txdata and txheaders.has_key('Content-type'):
txheaders['Content-length'] = str(len(txdata))     # we only need a
'Content-length' header if we have a 'Content-type' one...

theurl = 'http://www.someserver.com/somepath/somepage.html'         #
In actual fact I normally decode the url from the PATH_INFO

req = urllib2.Request(theurl, txdata, txheaders)         # create the
request object
try:
    u = urllib2.urlopen(req)        # fetch a handle on the url !
except IOError, e:
    if not hasattr(e,'code'):
        thecode = 0
    else:
        thecode = e.code
    print 'Content-type: text/html'
    print '<HTML><BODY><H1>Error Code %s</H1></BODY></HTML>' % e.code

info = u.info()         # info about the url
pagetype = info.gettype()
print 'Content-type: ' + pagetype + '\n'
print u.read()          # print the received page

###############################################################

In the code I actually use I make a logfile as well which logs txdata,
txheaders and all the environment variables.

Making a simple post to  my guestbook (
http://www.voidspace.xennos.com/cgi-bin/guestbook.py ) using this
method I get a 400 error.
>From the log I can see the following headers :
(printed using headername, '  :  ', value)

Connection    :    keep-alive
Accept-language    :    en-gb
Pragma    :    no-cache
Cache-control    :    max-age=259200
Content-type    :    application/x-www-form-urlencoded
Content-length    :    62
Accept    :    image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,
application/x-shockwave-flash, application/msword, */*
User-agent    :    Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)


And the following POST data :
name=Fuzzyman&email=&homepage=&location=&comment=CGI+post+test

Which even has a length of 62.... The only thing I can think of is
that the headers are appearing in the wrong order ?
Can anyone else see what I'm doing wrong ?

Regards,


Fuzzy
http://www.voidspace.org.uk/atlantibots/pythonutils.html



More information about the Python-list mailing list