Skip to content

Commit

Permalink
feat(router): compile time router
Browse files Browse the repository at this point in the history
Compile-time routes definition
  • Loading branch information
mookums authored Dec 18, 2024
2 parents a146f13 + 18a2a8d commit c3e26ed
Show file tree
Hide file tree
Showing 23 changed files with 1,502 additions and 1,287 deletions.
92 changes: 53 additions & 39 deletions docs/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ const log = std.log.scoped(.@"examples/basic");
const zzz = @import("zzz");
const http = zzz.HTTP;
const tardy = @import("tardy");
const tardy = zzz.tardy;
const Tardy = tardy.Tardy(.auto);
const Runtime = tardy.Runtime;
const Server = http.Server(.plain);
const Server = http.Server(.plain, *const i8);
const Router = Server.Router;
const Context = Server.Context;
const Route = Server.Route;
Expand All @@ -45,45 +45,59 @@ pub fn main() !void {
});
defer t.deinit();
var router = Router.init(allocator);
defer router.deinit();
const num: i8 = 12;
try router.serve_route("/", Route.init().get(&num, struct {
fn handler_fn(ctx: *Context, id: *const i8) !void {
const body_fmt =
\\ <!DOCTYPE html>
\\ <html>
\\ <body>
\\ <h1>Hello, World!</h1>
\\ <p>id: {d}</p>
\\ </body>
\\ </html>
;
const body = try std.fmt.allocPrint(ctx.allocator, body_fmt, .{id.*});
// This is the standard response and what you
// will usually be using. This will send to the
// client and then continue to await more requests.
try ctx.respond(.{
.status = .OK,
.mime = http.Mime.HTML,
.body = body[0..],
});
}
}.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));
var router = Router.init(&num, &[_]Route{
Route.init("/").get(struct {
fn handler_fn(ctx: *Context) !void {
const body_fmt =
\\ <!DOCTYPE html>
\\ <html>
\\ <body>
\\ <h1>Hello, World!</h1>
\\ <p>id: {d}</p>
\\ </body>
\\ </html>
;
const body = try std.fmt.allocPrint(ctx.allocator, body_fmt, .{ctx.state.*});
// This is the standard response and what you
// will usually be using. This will send to the
// client and then continue to await more requests.
try ctx.respond(.{
.status = .OK,
.mime = http.Mime.HTML,
.body = body[0..],
});
}
}.handler_fn),
Route.init("/echo").post(struct {
fn handler_fn(ctx: *Context) !void {
const body = if (ctx.request.body) |b|
try ctx.allocator.dupe(u8, b)
else
"";
try ctx.respond(.{
.status = .OK,
.mime = http.Mime.HTML,
.body = body[0..],
});
}
}.handler_fn),
}, .{
.not_found_handler = struct {
fn handler_fn(ctx: *Context) !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).
Expand Down
54 changes: 29 additions & 25 deletions docs/https.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const Server = http.Server(.{ .tls = .{
.key = .{ .file = .{ .path = "./examples/tls/certs/key.pem" } },
.cert_name = "CERTIFICATE",
.key_name = "EC PRIVATE KEY",
} });
} }, void);
const Context = Server.Context;
const Route = Server.Route;
Expand All @@ -37,33 +37,37 @@ pub fn main() !void {
const allocator = gpa.allocator();
defer _ = gpa.deinit();
var router = Router.init(allocator);
defer router.deinit();
var router = Router.init({}, &[_]Route{
Route.init("/embed/pico.min.css").serve_embedded_file(http.Mime.CSS, @embedFile("embed/pico.min.css")),
try router.serve_route("/", Route.init().get({}, struct {
pub fn handler_fn(ctx: *Context, _: void) !void {
const body =
\\ <!DOCTYPE html>
\\ <html>
\\ <body>
\\ <h1>Hello, World!</h1>
\\ </body>
\\ </html>
;
Route.init("/").get(struct {
pub fn handler_fn(ctx: *Context) !void {
const body =
\\ <!DOCTYPE html>
\\ <html>
\\ <head>
\\ <link rel="stylesheet" href="/embed/pico.min.css"/>
\\ </head>
\\ <body>
\\ <h1>Hello, World!</h1>
\\ </body>
\\ </html>
;
try ctx.respond(.{
.status = .OK,
.mime = http.Mime.HTML,
.body = body[0..],
});
}
}.handler_fn));
try ctx.respond(.{
.status = .OK,
.mime = http.Mime.HTML,
.body = body[0..],
});
}
}.handler_fn),
try router.serve_route("/kill", Route.init().get({}, struct {
pub fn handler_fn(ctx: *Context, _: void) !void {
ctx.runtime.stop();
}
}.handler_fn));
Route.init("/kill").get(struct {
pub fn handler_fn(ctx: *Context) !void {
ctx.runtime.stop();
}
}.handler_fn),
}, .{});
var t = try Tardy.init(.{
.allocator = allocator,
Expand Down
97 changes: 48 additions & 49 deletions examples/basic/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const tardy = zzz.tardy;
const Tardy = tardy.Tardy(.auto);
const Runtime = tardy.Runtime;

const Server = http.Server(.plain);
const Server = http.Server(.plain, *const i8);
const Router = Server.Router;
const Context = Server.Context;
const Route = Server.Route;
Expand All @@ -29,60 +29,59 @@ pub fn main() !void {
});
defer t.deinit();

var router = Router.init(allocator);
defer router.deinit();

const num: i8 = 12;

try router.serve_route("/", Route.init().get(&num, struct {
fn handler_fn(ctx: *Context, id: *const i8) !void {
const body_fmt =
\\ <!DOCTYPE html>
\\ <html>
\\ <body>
\\ <h1>Hello, World!</h1>
\\ <p>id: {d}</p>
\\ </body>
\\ </html>
;

const body = try std.fmt.allocPrint(ctx.allocator, body_fmt, .{id.*});
var router = Router.init(&num, &[_]Route{
Route.init("/").get(struct {
fn handler_fn(ctx: *Context) !void {
const body_fmt =
\\ <!DOCTYPE html>
\\ <html>
\\ <body>
\\ <h1>Hello, World!</h1>
\\ <p>id: {d}</p>
\\ </body>
\\ </html>
;

// This is the standard response and what you
// will usually be using. This will send to the
// client and then continue to await more requests.
try ctx.respond(.{
.status = .OK,
.mime = http.Mime.HTML,
.body = body[0..],
});
}
}.handler_fn));
const body = try std.fmt.allocPrint(ctx.allocator, body_fmt, .{ctx.state.*});

try router.serve_route("/echo", Route.init().post({}, struct {
fn handler_fn(ctx: *Context, _: void) !void {
const body = if (ctx.request.body) |b|
try ctx.allocator.dupe(u8, b)
else
"";
// This is the standard response and what you
// will usually be using. This will send to the
// client and then continue to await more requests.
try ctx.respond(.{
.status = .OK,
.mime = http.Mime.HTML,
.body = body[0..],
});
}
}.handler_fn),

try ctx.respond(.{
.status = .OK,
.mime = http.Mime.HTML,
.body = body[0..],
});
}
}.handler_fn));
Route.init("/echo").post(struct {
fn handler_fn(ctx: *Context) !void {
const body = if (ctx.request.body) |b|
try ctx.allocator.dupe(u8, b)
else
"";

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));
try ctx.respond(.{
.status = .OK,
.mime = http.Mime.HTML,
.body = body[0..],
});
}
}.handler_fn),
}, .{
.not_found_handler = struct {
fn handler_fn(ctx: *Context) !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).
Expand Down
12 changes: 6 additions & 6 deletions examples/benchmark/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const tardy = zzz.tardy;
const Tardy = tardy.Tardy(.auto);
const Runtime = tardy.Runtime;

const Server = http.Server(.plain);
const Server = http.Server(.plain, void);
const Context = Server.Context;
const Route = Server.Route;
const Router = Server.Router;
Expand All @@ -17,7 +17,7 @@ pub const std_options = .{
.log_level = .err,
};

fn hi_handler(ctx: *Context, _: void) !void {
fn hi_handler(ctx: *Context) !void {
const name = ctx.captures[0].string;

const body = try std.fmt.allocPrint(ctx.allocator,
Expand Down Expand Up @@ -60,10 +60,10 @@ pub fn main() !void {
});
defer t.deinit();

var router = Router.init(allocator);
defer router.deinit();
try router.serve_embedded_file("/", http.Mime.HTML, @embedFile("index.html"));
try router.serve_route("/hi/%s", Route.init().get({}, hi_handler));
var router = Router.init({}, &[_]Route{
Route.init("/").serve_embedded_file(http.Mime.HTML, @embedFile("index.html")),
Route.init("/hi/%s").get(hi_handler),
}, .{});

try t.entry(
&router,
Expand Down
Loading

0 comments on commit c3e26ed

Please sign in to comment.