Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Router Additions #13

Merged
merged 8 commits into from
Nov 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion examples/basic/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub fn main() !void {
const num: i8 = 12;

try router.serve_route("/", Route.init().get(&num, struct {
pub fn handler_fn(ctx: *Context, id: *const i8) !void {
fn handler_fn(ctx: *Context, id: *const i8) !void {
const body_fmt =
\\ <!DOCTYPE html>
\\ <html>
Expand All @@ -59,6 +59,16 @@ pub fn main() !void {
}
}.handler_fn));

router.serve_not_found(Route.init().get({}, struct {
fn handler_fn(ctx: *Context, _: void) !void {
try ctx.respond(.{
.status = .@"Not Found",
.mime = http.Mime.HTML,
.body = "Not Found Handler!",
});
}
}.handler_fn));

// This provides the entry function into the Tardy runtime. This will run
// exactly once inside of each runtime (each thread gets a single runtime).
try t.entry(
Expand Down
4 changes: 3 additions & 1 deletion examples/fs/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ pub fn main() !void {
&router,
struct {
fn entry(rt: *Runtime, r: *const Router) !void {
var server = Server.init(.{ .allocator = rt.allocator });
var server = Server.init(.{
.allocator = rt.allocator,
});
try server.bind(host, port);
try server.serve(r, rt);
}
Expand Down
2 changes: 1 addition & 1 deletion src/core/job.zig
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const TaskFn = @import("tardy").TaskFn;

pub const AfterType = union(enum) {
recv,
sse: struct {
other: struct {
func: *const anyopaque,
ctx: *anyopaque,
},
Expand Down
105 changes: 77 additions & 28 deletions src/http/context.zig
Original file line number Diff line number Diff line change
Expand Up @@ -38,60 +38,109 @@ pub fn Context(comptime Server: type) type {
triggered: bool = false,

pub fn to_sse(self: *Self, then: TaskFn(bool, *SSE)) !void {
assert(!self.triggered);
self.triggered = true;

self.response.set(.{
.status = .OK,
.body = "",
.mime = Mime{
.extension = ".sse",
.description = "Server-Sent Events",
.content_type = "text/event-stream",
},
});

const headers = try self.provision.response.headers_into_buffer(
self.provision.buffer,
null,
);

const sse = try self.allocator.create(SSE);
sse.* = .{
.context = self,
.runtime = self.runtime,
.allocator = self.allocator,
};

const pslice = Pseudoslice.init(headers, "", self.provision.buffer);
try self.respond_headers_only(
.{
.status = .OK,
.body = "",
.mime = Mime{
.extension = ".sse",
.description = "Server-Sent Events",
.content_type = "text/event-stream",
},
},
null,
sse,
then,
);
}

pub fn close(self: *Self) !void {
self.provision.job = .close;
try self.runtime.net.close(
self.provision,
Server.close_task,
self.provision.socket,
);
}

pub fn send_then(
self: *Self,
data: []const u8,
ctx: anytype,
then: TaskFn(bool, @TypeOf(ctx)),
) !void {
const pslice = Pseudoslice.init(data, "", self.provision.buffer);

const first_chunk = try Server.prepare_send(
self.runtime,
self.provision,
.{ .sse = .{
.func = then,
.ctx = sse,
} },
.{
.other = .{
.func = then,
.ctx = ctx,
},
},
pslice,
);

try self.runtime.net.send(
self.provision,
Server.send_then_sse_task,
Server.send_then_other_task,
self.provision.socket,
first_chunk,
);
}

pub fn close(self: *Self) !void {
self.provision.job = .close;
try self.runtime.net.close(
pub fn send_then_recv(self: *Self, data: []const u8) !void {
const pslice = Pseudoslice.init(data, "", self.provision.buffer);

const first_chunk = try Server.prepare_send(
self.runtime,
self.provision,
Server.close_task,
.recv,
pslice,
);

try self.runtime.net.send(
self.provision,
Server.send_then_recv_task,
self.provision.socket,
first_chunk,
);
}

// This will respond with the headers only.
// You will be in charge of sending the body.
pub fn respond_headers_only(
self: *Self,
options: ResponseSetOptions,
content_length: ?usize,
ctx: anytype,
then: TaskFn(bool, @TypeOf(ctx)),
) !void {
assert(!self.triggered);
self.triggered = true;

// the body should not be set.
assert(options.body == null);
self.response.set(options);

const headers = try self.provision.response.headers_into_buffer(
self.provision.buffer,
content_length,
);

try self.send_then(headers, ctx, then);
}

/// This is your standard response.
pub fn respond(self: *Self, options: ResponseSetOptions) !void {
assert(!self.triggered);
self.triggered = true;
Expand Down
2 changes: 1 addition & 1 deletion src/http/response.zig
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ pub const Response = struct {
}
}

pub fn headers_into_buffer(self: *Response, buffer: []u8, content_length: ?u32) ![]u8 {
pub fn headers_into_buffer(self: *Response, buffer: []u8, content_length: ?usize) ![]u8 {
var index: usize = 0;

// Status Line
Expand Down
2 changes: 1 addition & 1 deletion src/http/route.zig
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ pub fn Route(comptime Server: type) type {
// You can either give a void (if you don't want to pass data through) or a pointer.
comptime assert(@typeInfo(@TypeOf(data)) == .Pointer or @typeInfo(@TypeOf(data)) == .Void);
const inner_data = switch (comptime @typeInfo(@TypeOf(data))) {
.Void => @intFromPtr(&data),
.Void => 1, // Needs to not be 0.
.Pointer => @intFromPtr(data),
else => unreachable,
};
Expand Down
Loading
Loading