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

代理实现:如何复制并转发包含Null的服务器响应

代理响应转发:头体分离与后续数据包处理

我来帮你搞定这个代理转发响应的问题——你遇到的其实是HTTP代理里很常见的场景,核心难点就是准确分离首次响应的头和体,毕竟后续的数据包都是纯消息体,直接转发就行。

核心逻辑梳理

服务器返回的响应是流式传输的:

  • 第一个数据包大概率包含完整响应头 + 部分消息体,头和体之间用\r\n\r\n(两个连续的回车换行)作为分隔符
  • 后续所有数据包都是纯消息体,不需要处理头字段,直接转发给客户端即可

所以我们只需要聚焦两件事:

  1. 处理第一个数据包时,找到头体分隔符,修改响应头后再把「修改后的头+剩余体」转发给客户端
  2. 标记已处理过头字段,之后的数据包直接原样转发

具体实现方案

1. 基础状态与常量定义

先定义一个状态变量标记是否已经处理过响应头,同时指定HTTP头体分隔符:

#include <string.h>
#include <stdlib.h>
#include <stdbool.h>

// 上下文状态:标记是否已处理过响应头
bool has_processed_header = false;
// HTTP响应头与消息体的分隔符
const char* HEADER_SEPARATOR = "\r\n\r\n";

2. 首次响应处理(头体分离+修改)

在接收服务器响应的逻辑里,先判断是否未处理过头字段,再执行分离和修改操作:

void handle_server_response(int client_fd, char* res_buf, ssize_t recv_len) {
    if (!has_processed_header) {
        // 查找头体分隔符的位置
        char* sep_pos = strstr(res_buf, HEADER_SEPARATOR);
        if (sep_pos != NULL) {
            // 计算响应头的总长度(包含分隔符本身)
            size_t header_total_len = sep_pos - res_buf + strlen(HEADER_SEPARATOR);
            
            // 提取响应头并做修改
            char* modified_header = (char*)malloc(header_total_len);
            memcpy(modified_header, res_buf, header_total_len);
            // 这里添加你的头字段修改逻辑,比如替换Content-Length、添加自定义头
            // 举个例子:把Content-Type字段改成application/json
            char* ct_pos = strstr(modified_header, "Content-Type:");
            if (ct_pos != NULL) {
                char* line_end = strstr(ct_pos, "\r\n");
                if (line_end != NULL) {
                    size_t line_len = line_end - ct_pos;
                    snprintf(ct_pos, line_len, "Content-Type: application/json");
                }
            }
            
            // 拼接修改后的头和剩余的消息体
            size_t body_len = recv_len - header_total_len;
            char* forward_data = (char*)malloc(header_total_len + body_len);
            memcpy(forward_data, modified_header, header_total_len);
            memcpy(forward_data + header_total_len, sep_pos + strlen(HEADER_SEPARATOR), body_len);
            
            // 转发给客户端(替换成你的客户端socket发送逻辑)
            send(client_fd, forward_data, header_total_len + body_len, 0);
            
            // 清理内存,避免泄漏
            free(modified_header);
            free(forward_data);
            
            // 标记已处理头字段,后续数据包直接转发
            has_processed_header = true;
        } else {
            // 极端情况:首次数据包只有部分响应头(分隔符在后续包中)
            // 这时候需要把当前数据缓存起来,等下一个包到来后合并再查找分隔符
            // 示例:可以用静态缓冲区缓存不完整的响应头
            // static char header_cache[4096];
            // static size_t cache_len = 0;
            // memcpy(header_cache + cache_len, res_buf, recv_len);
            // cache_len += recv_len;
        }
    } else {
        // 后续数据包直接转发给客户端
        send(client_fd, res_buf, recv_len, 0);
    }
}

3. 关键注意事项

  • 缓冲区大小:你原来的res_buf是1024字节,可能不足以存储较长的响应头,建议换成更大的缓冲区(比如4096字节)或者实现动态缓存逻辑
  • 内存安全:使用malloc分配的内存一定要记得用free释放,避免内存泄漏
  • 异常场景处理:如果首次数据包找不到分隔符,必须缓存当前数据,等后续数据包合并后再处理,否则会丢失响应头内容

内容的提问来源于stack exchange,提问作者Mengge

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:34:50