python - 使用 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 类来访问表单字段值?
解决方案
在寻找解决方案大约一周后,我发现 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 解析器从表单中访问您需要的值。
推荐阅读
- python - 使用 ansible fact 过滤带有 fact = value 的接口
- webhooks - Mattermost 传入的 webhook:如何捆绑消息?
- powershell - 如何识别 Powershell 中的默认音频设备?
- cordova - cordova/phonegap inappbrowser 无法正确打开链接
- vue.js - 如何访问 Vue.js 中插槽中的值?
- c - Stackoverfflow 与 Msys2
- javascript - Return one item of string
- java - 如何通过 Spring Rest api 生成 aws cloudfront url?
- jmeter - 带有 Selenium WebDriver Sampler 的 JMeter 实际上使 PC 过载
- powershell - 是否可以以非管理员身份运行 Copy-VMFile powershell 命令?