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 Method = std.http.Method;
|
||||||
pub const Status = std.http.Status;
|
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 serveConn = server.serveConn;
|
||||||
pub const Response = server.Response;
|
pub const Response = server.Response;
|
||||||
pub const Handler = server.Handler;
|
pub const Handler = server.Handler;
|
||||||
|
|
||||||
pub const Fields = @import("./headers.zig").Fields;
|
pub const Fields = @import("./headers.zig").Fields;
|
||||||
|
|
||||||
pub const Headers = std.HashMap([]const u8, []const u8, struct {
|
pub const Protocol = enum {
|
||||||
pub fn eql(_: @This(), a: []const u8, b: []const u8) bool {
|
http_1_0,
|
||||||
return ciutf8.eql(a, b);
|
http_1_1,
|
||||||
}
|
http_1_x,
|
||||||
|
};
|
||||||
pub fn hash(_: @This(), str: []const u8) u64 {
|
|
||||||
return ciutf8.hash(str);
|
|
||||||
}
|
|
||||||
}, std.hash_map.default_max_load_percentage);
|
|
||||||
|
|
||||||
test {
|
|
||||||
_ = server;
|
|
||||||
_ = request;
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,14 +3,9 @@ const http = @import("./lib.zig");
|
||||||
|
|
||||||
const parser = @import("./request/parser.zig");
|
const parser = @import("./request/parser.zig");
|
||||||
|
|
||||||
pub const Request = struct {
|
pub fn Request(comptime _: type) type {
|
||||||
pub const Protocol = enum {
|
return struct {
|
||||||
http_1_0,
|
protocol: http.Protocol,
|
||||||
http_1_1,
|
|
||||||
http_1_x,
|
|
||||||
};
|
|
||||||
|
|
||||||
protocol: Protocol,
|
|
||||||
|
|
||||||
method: http.Method,
|
method: http.Method,
|
||||||
uri: []const u8,
|
uri: []const u8,
|
||||||
|
@ -18,15 +13,14 @@ pub const Request = struct {
|
||||||
|
|
||||||
body: ?[]const u8 = null,
|
body: ?[]const u8 = null,
|
||||||
|
|
||||||
pub fn parse(alloc: std.mem.Allocator, reader: anytype) !Request {
|
pub fn parseFree(self: *@This(), allocator: std.mem.Allocator) void {
|
||||||
return parser.parse(alloc, reader);
|
allocator.free(self.uri);
|
||||||
}
|
self.headers.deinit();
|
||||||
|
if (self.body) |body| allocator.free(body);
|
||||||
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,
|
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 method = try parseMethod(reader);
|
||||||
const uri = reader.readUntilDelimiterAlloc(alloc, ' ', max_path_len) catch |err| switch (err) {
|
const uri = reader.readUntilDelimiterAlloc(alloc, ' ', max_path_len) catch |err| switch (err) {
|
||||||
error.StreamTooLong => return error.RequestUriTooLong,
|
error.StreamTooLong => return error.RequestUriTooLong,
|
||||||
|
@ -47,7 +47,7 @@ pub fn parse(alloc: std.mem.Allocator, reader: anytype) !Request {
|
||||||
null;
|
null;
|
||||||
errdefer if (body) |b| alloc.free(b);
|
errdefer if (body) |b| alloc.free(b);
|
||||||
|
|
||||||
return Request{
|
return Request(@TypeOf(reader)){
|
||||||
.protocol = proto,
|
.protocol = proto,
|
||||||
|
|
||||||
.method = method,
|
.method = method,
|
||||||
|
@ -73,7 +73,7 @@ fn parseMethod(reader: anytype) !Method {
|
||||||
return error.MethodNotImplemented;
|
return error.MethodNotImplemented;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseProto(reader: anytype) !Request.Protocol {
|
fn parseProto(reader: anytype) !http.Protocol {
|
||||||
var buf: [8]u8 = undefined;
|
var buf: [8]u8 = undefined;
|
||||||
const proto = reader.readUntilDelimiter(&buf, '/') catch |err| switch (err) {
|
const proto = reader.readUntilDelimiter(&buf, '/') catch |err| switch (err) {
|
||||||
error.StreamTooLong => return error.UnknownProtocol,
|
error.StreamTooLong => return error.UnknownProtocol,
|
||||||
|
@ -159,9 +159,3 @@ fn parseEncoding(encoding: ?[]const u8) !Encoding {
|
||||||
if (std.mem.eql(u8, encoding.?, "chunked")) return .chunked;
|
if (std.mem.eql(u8, encoding.?, "chunked")) return .chunked;
|
||||||
return error.UnsupportedMediaType;
|
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 {
|
const test_case = struct {
|
||||||
fn parse(text: []const u8, expected: 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,
|
method: http.Method = .GET,
|
||||||
headers: []const std.meta.Tuple(&.{ []const u8, []const u8 }) = &.{},
|
headers: []const std.meta.Tuple(&.{ []const u8, []const u8 }) = &.{},
|
||||||
uri: []const u8 = "",
|
uri: []const u8 = "",
|
||||||
|
|
|
@ -3,6 +3,7 @@ const util = @import("util");
|
||||||
const http = @import("./lib.zig");
|
const http = @import("./lib.zig");
|
||||||
|
|
||||||
const response = @import("./server/response.zig");
|
const response = @import("./server/response.zig");
|
||||||
|
const request = @import("./request.zig");
|
||||||
|
|
||||||
pub const Response = struct {
|
pub const Response = struct {
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
|
@ -26,10 +27,6 @@ pub const Response = struct {
|
||||||
const Request = http.Request;
|
const Request = http.Request;
|
||||||
const request_buf_size = 1 << 16;
|
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 {
|
pub fn serveConn(conn: std.net.StreamServer.Connection, ctx: anytype, handler: anytype, alloc: std.mem.Allocator) !void {
|
||||||
// TODO: Timeouts
|
// TODO: Timeouts
|
||||||
while (true) {
|
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);
|
var arena = std.heap.ArenaAllocator.init(alloc);
|
||||||
defer arena.deinit();
|
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 {};
|
return handleError(conn.stream.writer(), err) catch {};
|
||||||
};
|
};
|
||||||
std.log.debug("done parsing", .{});
|
std.log.debug("done parsing", .{});
|
||||||
|
|
Loading…
Reference in a new issue