pgmql/lib/http.zig

101 lines
2.4 KiB
Zig
Raw Normal View History

const std = @import("std");
const zzz = @import("zzz");
const tardy = @import("tardy");
const _dispatchers = @import("dispatchers.zig");
const log = std.log.scoped(.@"pgmql/http");
/// HTTP API server structure.
pub const Server = struct {
const Self = @This();
const Tardy = tardy.Tardy(.auto);
const Http = zzz.HTTP.Server(.plain);
const Router = Http.Router;
const Route = Http.Route;
const Context = Http.Context;
allocator: std.mem.Allocator,
dispatchers: []const _dispatchers.Dispatcher,
/// Host to use.
host: []const u8 = "127.0.0.1",
/// Port to use.
port: u16 = 8122,
/// Tardy runtime, if initialized.
ta: ?Tardy = null,
/// HTTP router, if initialized.
router: ?Router = null,
/// Initialize a new HTTP API server.
pub fn init(allocator: std.mem.Allocator, dispatchers: []const _dispatchers.Dispatcher) Self {
return Self{
.allocator = allocator,
.dispatchers = dispatchers,
};
}
/// Deinitialize the HTTP API server.
pub fn deinit(self: *Self) void {
if (self.ta) |*_ta| {
_ta.deinit();
}
if (self.router) |*_router| {
_router.deinit();
}
}
/// Setup Tardy and ZZZ.
fn setup(self: *Self) !void {
self.ta = try Tardy.init(.{
.allocator = self.allocator,
.threading = .auto,
});
self.router = Router.init(self.allocator);
// Set error JSON response.
//TODO Improve zzz to allow this.
// Set not found JSON response.
self.router.?.serve_not_found(Route.init().get({}, struct {
fn f(context: *Context, _: void) !void {
// Return a "not found" error as JSON.
try context.respond(.{
.status = zzz.HTTP.Status.@"Not Found",
.body = "{\"error\": \"not found\"}",
.mime = zzz.HTTP.Mime.JSON,
});
}
}.f));
}
/// Add API endpoints for the given dispatchers.
fn addApi(self: *Self) !void {
for (self.dispatchers) |dispatcher| {
// Add an endpoint of each dispatcher.
_ = dispatcher;
}
}
/// Start the HTTP API server.
pub fn start(self: *Self) !void {
try self.setup();
try self.ta.?.entry(
self, struct { fn f(runtime: *tardy.Runtime, server: *const Server) !void {
// Start a new HTTP server with the provided configuration.
var http = Http.init(runtime.allocator, .{});
try http.bind(.{ .ip = .{ .host = server.host, .port = server.port } });
try http.serve(&server.router.?, runtime);
} }.f,
{}, struct { fn f(runtime: *tardy.Runtime, _: void) !void {
try Http.clean(runtime);
} }.f
);
}
};