Cannot get POST values with cgi.FieldStorage

In the original code, I just changed the line

form = cgi.FieldStorage()

to

form = cgi.FieldStorage(
    fp=self.rfile,
    headers=self.headers,
    environ={'REQUEST_METHOD':'POST'})

and it seems to work as you intended.

Hat-tip to http://pymotw.com/2/BaseHTTPServer/ for the critical 'environ' setting. (By default, cgi.FieldStorage thinks it's dealing with a GET request.)


I think you might be mixing some concepts here. You have both the idea of a server and also a cgi script. No matter what your POST action is (http.py or whatever), your server is just going to take in a request. No CGI processing is actually happening. So you can first adjust your html template to this for simplicity:

<form  method="post" action="">

Then, you should reference this other question about how to read from the request, as opposed to trying to use the cgi fieldstorage:

import urlparse

...

    def do_POST(self):
        length = int(self.headers.getheader('content-length'))
        postvars = urlparse.parse_qs(self.rfile.read(length), keep_blank_values=1)
        self.send_response(200)
        self.end_headers()
        self.wfile.write(postvars)

The issue you were having, and because this is a very low level way to create a web server app, if you read indefinitely from the input stream, it will keep going and block. You check the header for the content length and only read that many bytes. You don't have any need for the cgi module at all, because this is not a cgi script.

A cgi script works by the server seeing the request is for a file of a matching type and location, and executing it in a subprocess like a normal program. It feeds the process the args and then gets back a response to ship back to the client. If this were a cgi script, the server would be in one module, running forever, and the cgi code would be in another with much simpler code to check the request.

Tags:

Python

Http