使用CGI模块在Python http.server中访问表单数据值

时间:2019-05-30 17:37:18

标签: python html cgi

我正在尝试创建一个Python Web服务器,该服务器接受用户输入并向第三方API发出请求。用户输入是通过我创建的简单表单获得的。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Test Document</title>
</head>
<body>
    <form action="server.py" method="post">
        <label for="firstname">First Name</label>
        <input type="text" name="firstname" id="firstname"><br>
        <label for="lastname">Last Name</label>
        <input type="text" name="lastname" id="lastname"><br>
        <label for="url">URL</label>
        <input type="text" name="url" id="application-url"><br>
        <input type="submit" value="Submit">
    </form>
</body>
</html>

我将此文件命名为index.html。我的server.py文件如下所示:

import cgi
from http.server import HTTPServer, CGIHTTPRequestHandler

class TestServerHandler(CGIHTTPRequestHandler):
    def do_POST(self):
        if self.path == '/':
            self.path = './index.html'

        try:
            form = cgi.FieldStorage()
            firstname = form.getvalue('firstname')
            lastname = form.getvalue('lastname')
            url = form.getvalue('url')
            print(firstname + ' ' + lastname + ' ' + url)
            output=firstname + lastname + url
        except: 
            self.send_error(404, 'Bad request submitted.')

        self.end_headers()
        self.wfile.write(bytes(output, 'utf-8'))


test_server = HTTPServer(('localhost', 8080), TestServerHandler)
test_server.serve_forever()

然后我在终端上运行server.py文件,并在浏览器中转到http://localhost:8080/网址。但是,当我提交表单时,在浏览器中出现错误。终端输出显示错误,提示“无法将'str'与'nonetype'连接在一起”。基于此错误,表单值不会传递到此页面。要么HTTP服务器正在将它们作为查询参数传递。无论如何,我能否在HTTP服务器中使用cgi.FieldStorage类访问表单字段值?

2 个答案:

答案 0 :(得分:0)

在寻找解决方案大约一周后,我发现http.server Python模块与cgi模块并不真正兼容。 cgi模块在Python脚本内部使用,该Python脚本从Web服务器上的某些HTML文档传递了表单值(即,Web服务器的index.html页面上的表单,其中“ action”属性设置为相关的Python脚本) 。但是,为了使cgi模块能够访问传递给该脚本的表单值(通过cgi.FieldStorage()调用),该脚本必须在Web服务器中运行。上面的代码示例的问题在于,我创建的server.py脚本本身就是Web服务器。具体来说,它使用我创建的自定义请求处理程序类(TestServerHandler)创建HTTPServer的实例。我的自定义类继承了http.server模块中包含的CGIHTTPRequestHandler类。此类包含Do_POST方法。实现此方法时,任何传递给Python脚本的表单数据都包含在self.rfile实例变量内。为了访问此变量并获取表单数据,我编写了与此类似的代码。

content_length = int(self.headers['Content-Length'])
data_input = bytes.decode(self.rfile.read(content_length))

将form_data存储在data_input变量中之后,可以使用URL解析器从表单访问所需的值。

答案 1 :(得分:0)

FieldStorage类具有在this page上定义的构造函数。重要的参数是fpheadersenviron。 OP是正确的,因为CGI.FieldStorage()通常在CGI脚本中不带参数的情况下调用,在这种情况下,将为您填充参数。但是,我们可以使用CGIHTTPRequestHandler为我们提供的变量来创建FieldStorage对象:

form = cgi.FieldStorage(
        fp=self.rfile,
        headers=self.headers,
        environ={
            'REQUEST_METHOD': 'POST',
            'CONTENT_TYPE': self.headers['Content-Type'],
        }