如何使 CGIHTTPRequestHandler 使用 POST 数据执行我的 PHP 脚本

How to make CGIHTTPRequestHandler execute my PHP scripts with POST data

我目前正在尝试使用 Python 中的 http.server 模块来做一些简单的网络工作。 当我尝试将 POST 表单添加到我的脚本时,它没有收到 POST 数据,$_POST 是空的并且 file_get_contents('php://input') 也是如此。

这是我的 post_test.html:

#!/usr/bin/php

<!DOCTYPE html>
<html>
<body>

<form method="post" action="post_test.html">
  Name: <input type="text" name="fname">
  <input type="submit">
</form>

<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    // collect value of input field
    echo "RAW POST: " . file_get_contents('php://input') . "<br>";
    $name = $_POST['fname'];
    if (empty($name)) {
        echo "Name is empty";
    } else {
        echo $name;
    }
}
?>

</body>
</html>

这是我的服务器脚本:

import urllib.parse
from http.server import CGIHTTPRequestHandler, HTTPServer

hostName = "localhost"
serverPort = 8080

handler = CGIHTTPRequestHandler
handler.cgi_directories.append('/php-cgi')


class MyServer(handler):

    def do_GET(self):
        # get path without first '/' and without anything besides path and filename
        file = self.path[1:].split("?")[0].split("#")[0]
        # if the file is in the script list, execute from php-cgi, else load from webapp
        php_handle = ["post_test.html"]
        if file in php_handle:
            self.path = "/php-cgi" + self.path
        else:
            self.path = "/webapp" + self.path
        CGIHTTPRequestHandler.do_GET(self)

    def do_POST(self):
        # get path without first '/' and without anything besides path and filename
        file = self.path[1:].split("?")[0].split("#")[0]
        # if the file is in the script list, execute from php-cgi
        php_handle = ["post_test.html"]
        if file in php_handle:
            length = int(self.headers['Content-Length'])
            post_data = urllib.parse.parse_qs(self.rfile.read(length).decode('utf-8'))
            for key, data in post_data.items():
                self.log_message(key + ": " + str.join(", ", data))

            self.path = "/php-cgi" + self.path
            CGIHTTPRequestHandler.do_POST(self)

    def do_HEAD(self):
        CGIHTTPRequestHandler.do_HEAD(self)


if __name__ == "__main__":
    webServer = HTTPServer((hostName, serverPort), MyServer)
    try:
        webServer.serve_forever()
    except KeyboardInterrupt:
        pass
    webServer.server_close()
    print("Server stopped.")

好吧,我终于能够解决问题了:#!/usr/bin/php是错误的,应该是#!/usr/bin/php-cgi

原因php 没有使用 POST 数据,也无法将其提供给 php。 php-cgi 专为网络服务器而设计,可以处理。

Hwo 解决下一个问题: 要运行 php-cgi成功你必须在当前目录下创建一个php.ini,有两个设置。 第一个允许直接执行它,第二个设置脚本所在的目录。如果您不设置它,您将收到 404 not found.

php.ini:

cgi.force_redirect = 0
doc_root = /home/username/server-directory

其中 server-directory 文件夹是包含 php.ini 和 php-cgi 文件夹的文件夹。此外,文件夹的名称与 php-cgi 二进制文件无关,这只是我命名的错误。

如果您尝试重新创建它,它现在应该可以完美运行。