Add new context object
This commit is contained in:
parent
c141d537c8
commit
004568a907
2 changed files with 89 additions and 76 deletions
161
src/http.zig
161
src/http.zig
|
@ -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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
@ -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),
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue