简体   繁体   中英

Cannot get POST values with cgi.FieldStorage

I`m trying to send simple html page with form data to user with GET, and then receive variables from form with POST. HTML file looks like:

<HTML>
<title> My Title</title>
<body>
<form  method="post" action="http.py">
<input name="Name" type="text"/>
<input name="Submit" type="submit" value="Submit" />
</form>
</body>
</HTML>

Here is python script:

import os
import cgi
import sys
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler



class customHTTPServer(BaseHTTPRequestHandler):
        def do_GET(self):
                self.send_response(200)
                self.send_header('Content-type', 'text/html')
                self.end_headers()
                fh=open('index.html','r')
                self.wfile.write(fh.read())
                return

        def do_POST(self):
            form = cgi.FieldStorage()
            self.send_response(200)
            self.end_headers()
            self.wfile.write(form['Name'].value)


def main():
       try:
            server = HTTPServer(('',9111),customHTTPServer)
            print 'server started at port 8080'
            server.serve_forever()
       except KeyboardInterrupt:
            server.socket.close()

if __name__=='__main__':
       sys.exit(main())

But FieldStorage remains empty all the time. I already tried to check what is in self.rfile, and found that if i try to do self.rfile.readlines() , browser stuck and looks like script is waiting for the end of data stream. From where i should take Name variable that i`m submitting with POST?

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.

以下是在我的案例中获取POST变量的方法的URL 这里详细说明由JDI提供。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM