Make request generic based on reader

This commit is contained in:
jaina heartles 2022-11-05 03:09:59 -07:00
parent b46e82746c
commit 438c72b7e9
5 changed files with 31 additions and 55 deletions

View file

@ -10,24 +10,15 @@ pub const socket = @import("./socket.zig");
pub const Method = std.http.Method;
pub const Status = std.http.Status;
pub const Request = request.Request;
pub const Request = request.Request(std.net.Stream.Reader);
pub const serveConn = server.serveConn;
pub const Response = server.Response;
pub const Handler = server.Handler;
pub const Fields = @import("./headers.zig").Fields;
pub const Headers = std.HashMap([]const u8, []const u8, struct {
pub fn eql(_: @This(), a: []const u8, b: []const u8) bool {
return ciutf8.eql(a, b);
}
pub fn hash(_: @This(), str: []const u8) u64 {
return ciutf8.hash(str);
}
}, std.hash_map.default_max_load_percentage);
test {
_ = server;
_ = request;
}
pub const Protocol = enum {
http_1_0,
http_1_1,
http_1_x,
};

View file

@ -3,30 +3,24 @@ const http = @import("./lib.zig");
const parser = @import("./request/parser.zig");
pub const Request = struct {
pub const Protocol = enum {
http_1_0,
http_1_1,
http_1_x,
pub fn Request(comptime _: type) type {
return struct {
protocol: http.Protocol,
method: http.Method,
uri: []const u8,
headers: http.Fields,
body: ?[]const u8 = null,
pub fn parseFree(self: *@This(), allocator: std.mem.Allocator) void {
allocator.free(self.uri);
self.headers.deinit();
if (self.body) |body| allocator.free(body);
}
};
protocol: Protocol,
method: http.Method,
uri: []const u8,
headers: http.Fields,
body: ?[]const u8 = null,
pub fn parse(alloc: std.mem.Allocator, reader: anytype) !Request {
return parser.parse(alloc, reader);
}
pub fn parseFree(self: *Request, alloc: std.mem.Allocator) void {
parser.parseFree(alloc, self);
}
};
test {
_ = parser;
}
pub fn parse(alloc: std.mem.Allocator, reader: anytype) !Request(@TypeOf(reader)) {
return parser.parse(alloc, reader);
}

View file

@ -21,7 +21,7 @@ const Encoding = enum {
chunked,
};
pub fn parse(alloc: std.mem.Allocator, reader: anytype) !Request {
pub fn parse(alloc: std.mem.Allocator, reader: anytype) !Request(@TypeOf(reader)) {
const method = try parseMethod(reader);
const uri = reader.readUntilDelimiterAlloc(alloc, ' ', max_path_len) catch |err| switch (err) {
error.StreamTooLong => return error.RequestUriTooLong,
@ -47,7 +47,7 @@ pub fn parse(alloc: std.mem.Allocator, reader: anytype) !Request {
null;
errdefer if (body) |b| alloc.free(b);
return Request{
return Request(@TypeOf(reader)){
.protocol = proto,
.method = method,
@ -73,7 +73,7 @@ fn parseMethod(reader: anytype) !Method {
return error.MethodNotImplemented;
}
fn parseProto(reader: anytype) !Request.Protocol {
fn parseProto(reader: anytype) !http.Protocol {
var buf: [8]u8 = undefined;
const proto = reader.readUntilDelimiter(&buf, '/') catch |err| switch (err) {
error.StreamTooLong => return error.UnknownProtocol,
@ -159,9 +159,3 @@ fn parseEncoding(encoding: ?[]const u8) !Encoding {
if (std.mem.eql(u8, encoding.?, "chunked")) return .chunked;
return error.UnsupportedMediaType;
}
pub fn parseFree(allocator: std.mem.Allocator, request: *Request) void {
allocator.free(request.uri);
request.headers.deinit();
if (request.body) |body| allocator.free(body);
}

View file

@ -5,7 +5,7 @@ const t = std.testing;
const test_case = struct {
fn parse(text: []const u8, expected: struct {
protocol: http.Request.Protocol = .http_1_1,
protocol: http.Protocol = .http_1_1,
method: http.Method = .GET,
headers: []const std.meta.Tuple(&.{ []const u8, []const u8 }) = &.{},
uri: []const u8 = "",

View file

@ -3,6 +3,7 @@ const util = @import("util");
const http = @import("./lib.zig");
const response = @import("./server/response.zig");
const request = @import("./request.zig");
pub const Response = struct {
alloc: std.mem.Allocator,
@ -26,10 +27,6 @@ pub const Response = struct {
const Request = http.Request;
const request_buf_size = 1 << 16;
pub fn Handler(comptime Ctx: type) type {
return fn (Ctx, Request, *Response) void;
}
pub fn serveConn(conn: std.net.StreamServer.Connection, ctx: anytype, handler: anytype, alloc: std.mem.Allocator) !void {
// TODO: Timeouts
while (true) {
@ -37,7 +34,7 @@ pub fn serveConn(conn: std.net.StreamServer.Connection, ctx: anytype, handler: a
var arena = std.heap.ArenaAllocator.init(alloc);
defer arena.deinit();
const req = Request.parse(arena.allocator(), conn.stream.reader()) catch |err| {
const req = request.parse(arena.allocator(), conn.stream.reader()) catch |err| {
return handleError(conn.stream.writer(), err) catch {};
};
std.log.debug("done parsing", .{});