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;
}

访问结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值