You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何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>&-

现象与测试结果

  1. 启动服务器命令:
    python3 -m http.server --bind localhost --cgi 8000
    
  2. 服务器日志显示请求已接收:
    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 -
    
  3. 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
    
  4. 脚本单独运行功能正常:
    $ 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
    

问题定位与解决

核心原因

  1. 缺少Content-Length头:Python http.server依赖请求的Content-Length头来确定要传递给CGI脚本的数据长度,前端请求未设置该头,导致脚本中的cat命令一直等待标准输入结束,进程卡住。
  2. 不符合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.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 21:54:51