Make request generic based on reader
This commit is contained in:
parent
b46e82746c
commit
438c72b7e9
5 changed files with 31 additions and 55 deletions
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 = "",
|
||||
|
|
|
@ -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", .{});
|
||||
|
|
Loading…
Reference in a new issue