首页 > 解决方案 > 使用 CGI 模块在 Python http.server 中访问表单数据值

问题描述

我正在尝试创建一个 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/ url。但是,当我提交表单时,浏览器中出现错误。终端输出显示一个错误,提示“无法将“str”与“nonetype”连接起来。基于此错误,表单值未传递到此页面。或者 HTTP 服务器将它们作为查询参数传递。在任何情况下,我是否可以在我的 HTTP 服务器中使用 cgi.FieldStorage 类来访问表单字段值?

标签: pythonhtmlcgi

解决方案


在寻找解决方案大约一周后,我发现 http.server Python 模块与 cgi 模块并不真正兼容。cgi 模块用于 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 解析器从表单中访问您需要的值。


推荐阅读