Add new context object

This commit is contained in:
jaina heartles 2022-05-23 21:52:34 -07:00
parent c141d537c8
commit 004568a907
2 changed files with 89 additions and 76 deletions

View file

@ -153,7 +153,7 @@ fn handleHttpRequest(reader: Reader, writer: Writer, handler: Handler) anyerror!
const headers = try parseHeaders(allocator, reader); const headers = try parseHeaders(allocator, reader);
const has_body = (headers.get("Content-Length") orelse headers.get("Transfer-Encoding")) != null; const has_body = method.requestHasBody() and headers.get("Content-Length") != null;
const tfer_encoding = headers.get("Transfer-Encoding"); const tfer_encoding = headers.get("Transfer-Encoding");
if (tfer_encoding != null and !std.mem.eql(u8, tfer_encoding.?, "identity")) { if (tfer_encoding != null and !std.mem.eql(u8, tfer_encoding.?, "identity")) {
@ -165,88 +165,101 @@ fn handleHttpRequest(reader: Reader, writer: Writer, handler: Handler) anyerror!
return error.UnsupportedMediaType; return error.UnsupportedMediaType;
} }
var context = Context{ var ctx = Context{
.request = .{ .request = Request2{
.method = method, .method = method,
.path = path, .path = path,
.headers = headers, .headers = headers,
.body = if (has_body) reader else null,
},
.response = .{
.headers = HeaderMap.init(allocator),
.writer = writer,
}, },
.allocator = allocator, .allocator = allocator,
}; };
try handler(&context); if (has_body) {
const body_len = std.fmt.parseInt(usize, headers.get("Content-Length").?, 10) catch return error.BadRequest;
const body = try allocator.alloc(u8, body_len);
errdefer allocator.free(body);
if ((try reader.read(body)) != body_len) return error.BadRequest;
ctx.request.body = body;
}
defer if (has_body) allocator.free(ctx.request.body.?);
_ = ctx;
//try handler(&ctx);
_ = handler;
_ = writer;
_ = path;
} }
pub const Context = struct { pub const Context = struct {
const Request = struct { request: Request2,
method: Method,
path: []const u8,
headers: HeaderMap,
body: ?Reader,
};
const Response = struct {
headers: HeaderMap,
writer: Writer,
fn writeHeaders(self: *Response) !void {
var iter = self.headers.iterator();
var it = iter.next();
while (it != null) : (it = iter.next()) {
try self.writer.print("{s}: {s}\r\n", .{ it.?.key_ptr.*, it.?.value_ptr.* });
}
}
fn statusText(status: u16) []const u8 {
return switch (status) {
200 => "OK",
204 => "No Content",
404 => "Not Found",
else => "",
};
}
fn openInternal(self: *Response, status: u16) !void {
try self.writer.print("HTTP/1.1 {} {s}\r\n", .{ status, statusText(status) });
try self.writeHeaders();
try self.writer.writeAll("Connection: close\r\n"); // TODO
}
pub fn open(self: *Response, status: u16) !Writer {
try self.openInternal(status);
try self.writer.writeAll("\r\n");
return self.writer;
}
pub fn write(self: *Response, status: u16, body: []const u8) !void {
try self.openInternal(status);
if (body.len != 0) {
try self.writer.print("Content-Length: {}\r\n", .{body.len});
if (self.headers.get("Content-Type") == null) {
try self.writer.writeAll("Content-Type: application/octet-stream\r\n");
}
}
try self.writer.writeAll("\r\n");
if (body.len != 0) {
try self.writer.writeAll(body);
}
}
pub fn statusOnly(self: *Response, status: u16) !void {
try self.openInternal(status);
}
};
request: Request,
response: Response,
allocator: std.mem.Allocator, allocator: std.mem.Allocator,
}; };
pub const Response2 = struct {
status: Status,
headers: HeaderMap,
body: ?[]const u8 = null,
};
pub const Request2 = struct {
method: Method,
path: []const u8,
headers: HeaderMap,
body: ?[]const u8 = null,
};
const Response = struct {
headers: HeaderMap,
writer: Writer,
fn writeHeaders(self: *Response) !void {
var iter = self.headers.iterator();
var it = iter.next();
while (it != null) : (it = iter.next()) {
try self.writer.print("{s}: {s}\r\n", .{ it.?.key_ptr.*, it.?.value_ptr.* });
}
}
fn statusText(status: u16) []const u8 {
return switch (status) {
200 => "OK",
204 => "No Content",
404 => "Not Found",
else => "",
};
}
fn openInternal(self: *Response, status: u16) !void {
try self.writer.print("HTTP/1.1 {} {s}\r\n", .{ status, statusText(status) });
try self.writeHeaders();
try self.writer.writeAll("Connection: close\r\n"); // TODO
}
pub fn open(self: *Response, status: u16) !Writer {
try self.openInternal(status);
try self.writer.writeAll("\r\n");
return self.writer;
}
pub fn write(self: *Response, status: u16, body: []const u8) !void {
try self.openInternal(status);
if (body.len != 0) {
try self.writer.print("Content-Length: {}\r\n", .{body.len});
if (self.headers.get("Content-Type") == null) {
try self.writer.writeAll("Content-Type: application/octet-stream\r\n");
}
}
try self.writer.writeAll("\r\n");
if (body.len != 0) {
try self.writer.writeAll(body);
}
}
pub fn statusOnly(self: *Response, status: u16) !void {
try self.openInternal(status);
}
};

View file

@ -11,8 +11,8 @@ pub const ciutf8 = util.ciutf8;
//pub const io_mode = .evented; //pub const io_mode = .evented;
pub const router = routing.makeRouter(*http.Context, &[_]routing.RouteFn(*http.Context){ pub const router = routing.makeRouter(*http.Context, &[_]routing.RouteFn(*http.Context){
routing.makeRoute(.GET, "/", staticString("Index Page")), //routing.makeRoute(.GET, "/", staticString("Index Page")),
routing.makeRoute(.GET, "/abc", staticString("abc")), //routing.makeRoute(.GET, "/abc", staticString("abc")),
//routing.makeRoute(.GET, "/user/:id", getUser), //routing.makeRoute(.GET, "/user/:id", getUser),
//routing.makeRoute(.POST, "/note/", postNote), //routing.makeRoute(.POST, "/note/", postNote),
}); });