当前位置: 首页 > news >正文

python实现简单fast-cgi服务,对接到nginx

python代码

import socket
import struct
import threading

# FastCGI 头格式(8 字节)
FCGI_HEADER_FORMAT = "!BBHHBx"
FCGI_VERSION = 1
FCGI_TYPE_BEGIN_REQUEST = 1
FCGI_TYPE_PARAMS = 4
FCGI_TYPE_STDIN = 5
FCGI_TYPE_STDOUT = 6
FCGI_TYPE_END_REQUEST = 3
FCGI_RESPONDER = 1

def parse_fcgi_header(data):
    """解析 FastCGI 头"""
    version, type_, request_id, content_length, padding_length = struct.unpack(FCGI_HEADER_FORMAT, data)
    return version, type_, request_id, content_length, padding_length

def read_fcgi_record(client_socket):
    """读取并解析 FastCGI 记录"""
    header = client_socket.recv(8)  # 读取 8 字节头部
    if not header:
        return None, None, None, None, None
    version, type_, request_id, content_length, padding_length = parse_fcgi_header(header)
    content = client_socket.recv(content_length) if content_length > 0 else b""
    client_socket.recv(padding_length)  # 读取并丢弃填充数据
    return type_, request_id, content, content_length, padding_length

def parse_fcgi_params(data):
    """解析 FastCGI PARAMS(key-value 形式)"""
    params = {}
    i = 0
    while i < len(data):
        name_length = data[i]
        value_length = data[i + 1]
        i += 2

        # 处理长度值大于 127 的情况
        if name_length >= 128:
            name_length = ((name_length & 0x7F) << 24) | (data[i] << 16) | (data[i+1] << 8) | data[i+2]
            i += 3
        if value_length >= 128:
            value_length = ((value_length & 0x7F) << 24) | (data[i] << 16) | (data[i+1] << 8) | data[i+2]
            i += 3

        name = data[i : i + name_length].decode("utf-8", errors="ignore")
        value = data[i + name_length : i + name_length + value_length].decode("utf-8", errors="ignore")
        params[name] = value
        i += name_length + value_length

    return params

def handle_request(client_socket):
    """处理 FastCGI 请求"""
    try:
        # 读取 BEGIN_REQUEST 记录
        type_, request_id, content, _, _ = read_fcgi_record(client_socket)
        if type_ != FCGI_TYPE_BEGIN_REQUEST:
            client_socket.close()
            return

        # 读取所有 PARAMS(FastCGI 请求参数)
        params_data = b""
        while True:
            type_, _, content, content_length, _ = read_fcgi_record(client_socket)
            if type_ != FCGI_TYPE_PARAMS or content_length == 0:
                break  # 读取完成
            params_data += content

        # **使用修正的解析函数**
        param_dict = parse_fcgi_params(params_data)
        print("Received FCGI Params:", param_dict)

        # 读取 STDIN(HTTP 请求体)
        stdin_data = b""
        while True:
            type_, _, content, content_length, _ = read_fcgi_record(client_socket)
            if type_ != FCGI_TYPE_STDIN or content_length == 0:
                break
            stdin_data += content

        # 生成 HTTP 响应
        response_body = b"Hello, FastCGI over TCP! (Threaded)"
        response_headers = b"Content-Type: text/plain\r\nContent-Length: %d\r\n\r\n" % len(response_body)
        stdout_data = response_headers + response_body

        # 发送 FastCGI 响应
        stdout_header = struct.pack(FCGI_HEADER_FORMAT, FCGI_VERSION, FCGI_TYPE_STDOUT, request_id, len(stdout_data), 0)
        end_header = struct.pack(FCGI_HEADER_FORMAT, FCGI_VERSION, FCGI_TYPE_END_REQUEST, request_id, 0, 0)

        client_socket.sendall(stdout_header + stdout_data)  # 发送正文
        client_socket.sendall(end_header)  # 发送结束标志
    except Exception as e:
        print(f"Error handling request: {e}")
    finally:
        client_socket.close()

def start_fcgi_server(host="0.0.0.0", port=9000):
    """启动 FastCGI 多线程 TCP 服务器"""
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server_socket.bind((host, port))
    server_socket.listen(5)
    print(f"FastCGI Server listening on {host}:{port}")

    while True:
        client_socket, _ = server_socket.accept()
        thread = threading.Thread(target=handle_request, args=(client_socket,))
        thread.start()  # 启动新线程处理请求

if __name__ == "__main__":
    start_fcgi_server()

nginx添加配置

location /hello {
    include fastcgi_params;
    fastcgi_pass 127.0.0.1:9000;
    
    # 传递 FastCGI 相关参数
    fastcgi_param REQUEST_METHOD $request_method;
    fastcgi_param SCRIPT_FILENAME /dummy;
    fastcgi_param QUERY_STRING $query_string;
    fastcgi_param CONTENT_TYPE $content_type;
    fastcgi_param CONTENT_LENGTH $content_length;
    fastcgi_param PATH_INFO $fastcgi_script_name;
}

访问结果

http://www.dtcms.com/a/107257.html

相关文章:

  • 蓝桥云客 刷题统计
  • 持续集成与Jenkins安装使用教程
  • 分布式锁方案-Redisson
  • Linux命令-tar
  • 使用 MapReduce 进行高效数据清洗:从理论到实践
  • Linux内核中ARP协议的实现与dev_addr字段的作用
  • LabVIEW 调用 Python 函数
  • SAP-ABAP:ABAP `LEAVE LIST-PROCESSING` 深度解析
  • 天梯赛 L2-023 图着色问题
  • ai prompt工程师认证
  • AT_abc306_b [ABC306B] Base 2
  • 【工具变量】全国分省低空经济高质量发展数据(2012-2023年)
  • Word 插入无页眉页码的空白页(即插入奇数页)
  • WebSocket connection failed 解决
  • 基于机器学习的三国时期诸葛亮北伐失败因素量化分析
  • 数学知识集锦
  • Ubuntu24.04-中文输入法的切换
  • 批量将文本文件转换为 Word/PDF/Excel/图片等其它格式
  • python-leetcode 64.在排序数组中查找元素的第一个和最后一个位置
  • c语言大小端判断
  • 【JavaScript】十三、事件监听与事件类型
  • 95. 费解的开关
  • 密码学基础——古典密码学
  • 云端革命:数字文明的重构与新生
  • int main(int argc, char **argv)C语言主函数参数解析
  • 【AI News | 20250402】每日AI进展
  • JavaScript基础-移动端常见特效
  • 代码训练营day22
  • leetcode 62. Unique Paths
  • Npfs!NpFsdWrite函数和Npfs!NpCommonWrite函数和Npfs!NpWriteDataQueue函数中的DeferredList