为何Python http.server无法向CGI脚本传递数据?
Python http.server CGI进程卡住问题排查
问题背景
测试Python http.server的传统CGI功能,实现前端"添加客户"表单数据提交到后端,由CGI脚本接收并写入文件,但出现以下异常:
- CGI进程启动后永不终止
- 未向目标文本文件写入任何内容
相关代码
前端HTML代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Add New Customer</title> <script> function submitForm() { // 测试发送字符串 fixedLengthData = "FOO TEST STRING"; console.log(fixedLengthData); // 发送POST请求到CGI后端 fetch('/cgi-bin/customer_add', { method: 'POST', headers: { 'Content-Type': 'text/plain' }, body: fixedLengthData }) .then(response => { if (!response.ok) { throw new Error('Network response was not ok ' + response.statusText); } return response; }) .catch(error => { console.error('There was a problem with the fetch operation:', error); }); } </script> </head> <body> <h1>Add New Customer</h1> <form id="customerForm" onsubmit="event.preventDefault(); submitForm();"> <label for="CUSTOMER-ID">Customer ID:</label> <input type="text" id="CUSTOMER-ID" name="CUSTOMER-ID" maxlength="4" required><br> <label for="CUSTOMER-NAME">Customer Name:</label> <input type="text" id="CUSTOMER-NAME" name="CUSTOMER-NAME" maxlength="50" required><br> <label for="CUSTOMER-EMAIL">Email:</label> <input type="email" id="CUSTOMER-EMAIL" name="CUSTOMER-EMAIL" maxlength="100"><br> <button type="submit">Add Customer</button> </form> </body> </html>
后端CGI脚本(位于cgi-bin目录)
#!/bin/sh # 打开test.txt文件用于写入 exec 3> test.txt # 读取标准输入所有内容到变量 input=$(cat) # 将内容写入文件 echo "$input" >&3 # 关闭文件 exec 3>&-
现象与测试结果
- 启动服务器命令:
python3 -m http.server --bind localhost --cgi 8000 - 服务器日志显示请求已接收:
Serving HTTP on ::1 port 8000 (http://[::1]:8000/) ... ::1 - - [30/Aug/2024 02:39:27] "POST /cgi-bin/customer_add HTTP/1.1" 200 - ps命令显示CGI进程未终止:user 24194 0.0 0.0 13556 2644 10 S+ 02:39 0:00.00 /bin/sh /home/user/test/cgi-bin/customer_add- 脚本单独运行功能正常:
$ echo -n "FOO TEST STRING" | ./customer_add $ ls -ltr total 64 -rwxrwxr-x 1 user user 209 Aug 30 02:37 customer_add -rw-rw-r-- 1 user user 4 Aug 30 02:37 test.txt $ cat test.txt FOO TEST STRING
问题定位与解决
核心原因
- 缺少Content-Length头:Python http.server依赖请求的
Content-Length头来确定要传递给CGI脚本的数据长度,前端请求未设置该头,导致脚本中的cat命令一直等待标准输入结束,进程卡住。 - 不符合CGI规范:CGI脚本未输出任何HTTP响应头(至少需要
Content-Type),服务器无法正确处理响应,间接导致进程异常。
修复方案
方案1:前端添加Content-Length头
修改fetch请求的headers,手动计算并添加内容长度:
fetch('/cgi-bin/customer_add', { method: 'POST', headers: { 'Content-Type': 'text/plain', 'Content-Length': fixedLengthData.length.toString() }, body: fixedLengthData })
方案2:CGI脚本添加响应头并兼容CONTENT_LENGTH环境变量
修改脚本,先输出响应头,再通过环境变量读取指定长度的输入:
#!/bin/sh # 输出CGI标准响应头 echo "Content-Type: text/plain" echo "" exec 3> test.txt # 通过CONTENT_LENGTH环境变量读取指定长度的输入 input=$(dd bs=1 count=$CONTENT_LENGTH 2>/dev/null) echo "$input" >&3 exec 3>&- # 可选:输出响应内容告知前端 echo "Data saved successfully"
修改后,CGI脚本将正确接收数据、写入文件并正常终止进程。
内容的提问来源于stack exchange,提问作者M.E.
相关产品推荐
相关产品推荐

