POST请求JSON数据提取失败及Content-Type校验问题
在Zig HTTP服务中读取JSON请求并校验Content-Type
一、校验Content-Type请求头
要确认请求的Content-Type是否为application/json,可以通过request.headers的getFirstValue方法获取对应字段值,再做字符串比对:
pub fn post(response: *http.Server.Response) void { response.do() catch |e| { std.log.err("{any}", .{e}); return; }; if (response.request.method != .HEAD) { // 获取Content-Type字段 const content_type = response.request.headers.getFirstValue("Content-Type") orelse { std.log.err("Missing Content-Type header", .{}); response.status = .unsupported_media_type; return; }; // 校验是否为application/json if (!std.mem.eql(u8, content_type, "application/json")) { std.log.err("Invalid Content-Type: expected application/json", .{}); response.status = .unsupported_media_type; return; } std.log.debug("Valid JSON request received", .{}); } }
二、读取并解析JSON内容
Zig HTTP服务的请求体需要通过response.reader()读取,结合请求头中的content_length指定长度获取数据,再用std.json模块解析为对应结构体:
1. 定义JSON对应的结构体
先声明与请求JSON结构匹配的Zig结构体:
const LoginRequest = struct { login: []const u8, password: []const u8, };
2. 读取请求体并解析JSON
在处理函数中添加读取和解析逻辑:
pub fn post(response: *http.Server.Response) void { response.do() catch |e| { std.log.err("{any}", .{e}); return; }; if (response.request.method != .HEAD) { // 省略Content-Type校验代码(同上) const reader = response.reader(); var gpa = std.heap.GeneralPurposeAllocator(.{}){}; defer _ = gpa.deinit(); const allocator = gpa.allocator(); // 根据content_length读取完整请求体 const body = reader.readAllAlloc(allocator, response.request.content_length orelse 0) catch |e| { std.log.err("Failed to read request body: {any}", .{e}); response.status = .bad_request; return; }; defer allocator.free(body); // 解析JSON到结构体 const parsed_request = std.json.parse(LoginRequest, &std.json.TokenStream.init(body), .{ .allocator = allocator }) catch |e| { std.log.err("Failed to parse JSON: {any}", .{e}); response.status = .bad_request; return; }; defer parsed_request.deinit(); // 使用解析后的数据 std.log.info("Login: {s}, Password: {s}", .{ parsed_request.value.login, parsed_request.value.password }); } }
注意事项
- 若请求采用分块传输编码(
content_length为null),需循环读取直到流结束 - 所有通过分配器申请的内存要记得及时释放,避免泄漏
- 可根据需求调整
std.json.ParseOptions参数,比如忽略未知字段
内容的提问来源于stack exchange,提问作者Hasan A Yousef
相关产品推荐
相关产品推荐

