- static.c: 新增 brotli_compress(),使用 libbrotlienc(质量 11,窗口 22) - static_serve_file(): 优先 Brotli,回退 Gzip,二进制文件跳过 - http.c: 解析 Accept-Encoding: br,http_request_t 新增 accept_brotli - cocoon.h: cocoon_config_t 新增 brotli_enabled(默认 true) - config.c/h: 解析 brotli_enabled JSON 字段,config_merge() 新增 has_brotli_enabled - main.c: --no-brotli 命令行选项 - server.c: 连接结构体新增 brotli_enabled - Makefile: 链接 -lbrotlienc - 单元测试: test_static.c 新增 4 个 Brotli 测试;test_config.c 新增 brotli 配置测试 - 集成测试: 新增 5 项 Brotli 测试(br 压缩、优先策略、图片不压缩) - cocoon.json: 添加 brotli_enabled 字段 - README: 更新特性描述、curl 示例、命令行参数、路线图 - 113 个单元测试全部通过,37 项集成测试全部通过
136 lines
3.2 KiB
C
136 lines
3.2 KiB
C
/**
|
||
* http.h - HTTP 解析模块接口
|
||
*
|
||
* 提供 HTTP 请求解析和响应构建的接口。
|
||
*
|
||
* @author xfy
|
||
*/
|
||
|
||
#ifndef COCOON_HTTP_H
|
||
#define COCOON_HTTP_H
|
||
|
||
#include <stdint.h>
|
||
#include <stdbool.h>
|
||
#include <stddef.h>
|
||
|
||
/* === HTTP 方法 === */
|
||
typedef enum {
|
||
HTTP_GET,
|
||
HTTP_HEAD,
|
||
HTTP_POST,
|
||
HTTP_PUT,
|
||
HTTP_DELETE,
|
||
HTTP_OPTIONS,
|
||
HTTP_UNKNOWN
|
||
} http_method_t;
|
||
|
||
/* === HTTP 请求 === */
|
||
#define HTTP_MAX_PATH 4096
|
||
#define HTTP_MAX_HEADERS 32
|
||
#define HTTP_HEADER_NAME_MAX 64
|
||
#define HTTP_HEADER_VALUE_MAX 1024
|
||
#define HTTP_MAX_BODY 8388608 /* 8MB 最大请求体 */
|
||
|
||
typedef struct {
|
||
http_method_t method;
|
||
char path[HTTP_MAX_PATH];
|
||
char version[16];
|
||
|
||
/* 请求头 */
|
||
struct {
|
||
char name[HTTP_HEADER_NAME_MAX];
|
||
char value[HTTP_HEADER_VALUE_MAX];
|
||
} headers[HTTP_MAX_HEADERS];
|
||
int num_headers;
|
||
|
||
/* 常用头快速访问 */
|
||
int64_t content_length;
|
||
bool keep_alive;
|
||
bool has_range;
|
||
int64_t range_start;
|
||
int64_t range_end;
|
||
|
||
/* 缓存相关头 */
|
||
char if_none_match[64];
|
||
char if_modified_since[64];
|
||
bool has_if_none_match;
|
||
bool has_if_modified_since;
|
||
|
||
/* 压缩相关头 */
|
||
bool accept_gzip; /* 客户端支持 gzip */
|
||
bool accept_brotli; /* 客户端支持 brotli */
|
||
bool accept_deflate; /* 客户端支持 deflate */
|
||
bool has_accept_encoding;
|
||
|
||
/* 请求体 */
|
||
char *body; /* 请求体数据(动态分配) */
|
||
size_t body_len; /* 请求体实际长度 */
|
||
char content_type[HTTP_HEADER_VALUE_MAX]; /* 解析后的 Content-Type */
|
||
} http_request_t;
|
||
|
||
/* === HTTP 响应 === */
|
||
typedef struct {
|
||
int status_code;
|
||
const char *status_text;
|
||
const char *content_type;
|
||
int64_t content_length;
|
||
bool keep_alive;
|
||
bool has_range;
|
||
int64_t range_start;
|
||
int64_t range_end;
|
||
int64_t total_length;
|
||
|
||
/* 缓存 */
|
||
const char *etag;
|
||
const char *last_modified;
|
||
|
||
/* 压缩 */
|
||
const char *content_encoding;
|
||
} http_response_t;
|
||
|
||
/* === API === */
|
||
/**
|
||
* http_parse_request - 从缓冲区解析 HTTP 请求
|
||
*
|
||
* @param buf 输入缓冲区
|
||
* @param len 缓冲区长度
|
||
* @param req 输出请求结构体
|
||
* @return 成功解析的字节数,< 0 表示错误(-1 = 不完整,-2 = 格式错误)
|
||
*/
|
||
int http_parse_request(const char *buf, size_t len, http_request_t *req);
|
||
|
||
/**
|
||
* http_format_response_header - 格式化响应头到缓冲区
|
||
*
|
||
* @param buf 输出缓冲区
|
||
* @param buf_size 缓冲区大小
|
||
* @param resp 响应信息
|
||
* @return 写入的字节数,< 0 表示缓冲区不足
|
||
*/
|
||
int http_format_response_header(char *buf, size_t buf_size, const http_response_t *resp);
|
||
|
||
/**
|
||
* http_method_str - HTTP 方法转字符串
|
||
*
|
||
* @param method HTTP 方法
|
||
* @return 方法字符串(如 "GET")
|
||
*/
|
||
const char *http_method_str(http_method_t method);
|
||
|
||
/**
|
||
* http_request_free - 释放 HTTP 请求中动态分配的资源
|
||
*
|
||
* @param req 请求结构体
|
||
*/
|
||
void http_request_free(http_request_t *req);
|
||
|
||
/**
|
||
* http_mime_type - 根据文件扩展名获取 MIME 类型
|
||
*
|
||
* @param path 文件路径
|
||
* @return MIME 类型字符串
|
||
*/
|
||
const char *http_mime_type(const char *path);
|
||
|
||
#endif /* COCOON_HTTP_H */
|