tiny.http.Response
Defined in tiny.http.
API (13)
Actions
Public operations.
Fields and members
Public fields and members.
Source
Source: lib/http/src/response.zig:275
zig
pub const Response = struct { status: u16, status_text: []const u8, headers: Headers, body: ?[]const u8, body_release: ?BodyRelease, head_storage: []u8, const BodyRelease = struct { context: *anyopaque, callback: *const fn (*anyopaque, []const u8) void, body: []const u8, }; pub fn init(scratch: Scratch) Response { return .{ .status = 200, .status_text = "OK", .headers = .{ .entries = scratch.headers, .length = 0 }, .body = null, .body_release = null, .head_storage = scratch.head, }; } pub fn deinit(self: *Response) void { if (self.body_release) |release| { release.callback(release.context, release.body); } self.body = null; self.body_release = null; } pub fn setBodyWithRelease( self: *Response, body: []const u8, context: anytype, comptime release_body: anytype, ) void { const Context = @TypeOf(context); const info = @typeInfo(Context); if (info != .pointer or info.pointer.size != .one) { @compileError("response body release context must be a single-item pointer"); } const Erased = struct { fn release(erased: *anyopaque, bytes: []const u8) void { const typed: Context = @ptrCast(@alignCast(erased)); release_body(typed, bytes); } }; self.deinit(); self.body = body; self.body_release = .{ .context = @ptrCast(@constCast(context)), .callback = Erased.release, .body = body, }; } pub fn setHeader(self: *Response, name: []const u8, value: []const u8) Error!void { try self.headers.set(name, value); } pub fn serialize(self: *const Response) Error!Serialized { return self.serializeWithOptions(.{}); } pub fn serializeForMethod(self: *const Response, method: Request.Method) Error!Serialized { return self.serializeWithOptions(.{ .method = method }); } pub fn switchingProtocols(scratch: Scratch, accept_key: []const u8) Error!Response { if (scratch.headers.len < 3) return error.HeaderCapacityExceeded; var response = Response.init(scratch); response.status = 101; response.status_text = "Switching Protocols"; try response.setHeader("Upgrade", "websocket"); try response.setHeader("Connection", "Upgrade"); try response.setHeader("Sec-WebSocket-Accept", accept_key); return response; } fn serializeWithOptions(self: *const Response, options: SerializeOptions) Error!Serialized { const head_length = try self.serializedHeadLength(); if (head_length > self.head_storage.len) return error.HeadCapacityExceeded; var fixed = std.Io.Writer.fixed(self.head_storage[0..head_length]); const writer = &fixed; writer.print("HTTP/1.1 {d} {s}\r\n", .{ self.status, self.status_text }) catch unreachable; for (self.headers.entries[0..self.headers.length]) |entry| { if (!self.shouldWriteHeader(entry.name)) continue; writer.print("{s}: {s}\r\n", .{ entry.name, entry.value }) catch unreachable; } if (self.body) |body| { if (self.shouldWriteContentLength() and !self.headers.contains("Content-Length")) { writer.print("Content-Length: {d}\r\n", .{body.len}) catch unreachable; } } writer.writeAll("\r\n") catch unreachable; std.debug.assert(writer.buffered().len == head_length); return .{ .head = writer.buffered(), .body = if (self.shouldWriteBody(options)) self.body else null, }; } fn serializedHeadLength(self: *const Response) Error!usize { var length: usize = 0; length = try addLength(length, "HTTP/1.1 ".len); length = try addLength(length, decimalLength(self.status)); length = try addLength(length, " ".len); length = try addLength(length, self.status_text.len); length = try addLength(length, "\r\n".len); for (self.headers.entries[0..self.headers.length]) |entry| { if (!self.shouldWriteHeader(entry.name)) continue; length = try addLength(length, entry.name.len); length = try addLength(length, ": ".len); length = try addLength(length, entry.value.len); length = try addLength(length, "\r\n".len); } if (self.body) |body| { if (self.shouldWriteContentLength() and !self.headers.contains("Content-Length")) { length = try addLength(length, "Content-Length: ".len); length = try addLength(length, decimalLength(body.len)); length = try addLength(length, "\r\n".len); } } return addLength(length, "\r\n".len); } fn shouldWriteHeader(self: *const Response, name: []const u8) bool { if (std.ascii.eqlIgnoreCase(name, "Transfer-Encoding")) { return self.statusAllowsBody(); } if (std.ascii.eqlIgnoreCase(name, "Content-Length")) { return self.statusAllowsContentLength(); } return true; } fn shouldWriteContentLength(self: *const Response) bool { return self.statusAllowsContentLength(); } fn shouldWriteBody(self: *const Response, options: SerializeOptions) bool { if (self.body == null) return false; if (!self.statusAllowsBody()) return false; if (options.method) |method| { if (method == .HEAD) return false; } return true; } fn statusAllowsBody(self: *const Response) bool { if (self.status >= 100 and self.status < 200) return false; return self.status != 204 and self.status != 304; } fn statusAllowsContentLength(self: *const Response) bool { if (self.status >= 100 and self.status < 200) return false; return self.status != 204; }};Source: lib/http/src/root.zig:48
zig
pub const Response = response.Response;Audit
| Definitions | 8 |
|---|---|
| Public names | 8 |
| Members | 6 |
| Version | 26.7.0 |
| Revision | daab053ee433 |