HTTP library for Odin
Find a file
2025-11-13 16:40:18 +01:00
http Replace work queue with Odin core thread pool 2025-11-13 11:18:48 +01:00
.gitignore Initial commit 2025-11-03 13:50:38 +01:00
.gitmodules Add routing 2025-11-09 11:11:15 +01:00
fjord_test.odin Make thread count adjustable 2025-11-13 16:40:18 +01:00
odinfmt.json Initial commit 2025-11-03 13:50:38 +01:00
README.md Make thread count adjustable 2025-11-13 16:40:18 +01:00
router.odin Replace work queue with Odin core thread pool 2025-11-13 11:18:48 +01:00
server.odin Make thread count adjustable 2025-11-13 16:40:18 +01:00

HTTP 1/1 server library

Routing rules

  • Static first routing
  • Path variables defined with :foo
  • Example: /odin/:version/download
  • Wild card routing not implemented

Compile time user errors included

When defining the server you can pass a custom error type for the server. All the handler function will, of course, need to return these in as a pair with a response.

Memory allocation

The server will free the context temp allocators memory after the handler is run, thus, you are free to use context.temp_allocator within your handlers and expect the memory to be freed after. This becomes useful when you want to pass the response back to the server but is also ergonomic if you find yourself in need of a temp allocator in your handlers.

Example

package main

import "core:log"
import "core:net"
import "core:strings"
import fjord "fjord"
import http "fjord/http"

// Handler for GET /hello/:name
hello_handler :: proc(request: ^http.Request) -> (http.Response, Error) {
    name := request.path_variables["name"]

    body := strings.concatenate(
        {"<h1>Hello, ", name, "!</h1>"},
        context.temp_allocator,
    )

    response := http.make_response(
        .Ok,
        transmute([]byte)body,
        .Html,
        context.temp_allocator,
    )

    return response, nil
}

// Handler for GET /users/:id/posts/:post_id
user_post_handler :: proc(request: ^http.Request) -> (http.Response, Error) {
    user_id := request.path_variables["id"]
    post_id := request.path_variables["post_id"]

    body := strings.concatenate(
        {"<p>User ", user_id, " - Post ", post_id, "</p>"},
        context.temp_allocator,
    )

    response := http.make_response(
        .Ok,
        transmute([]byte)body,
        .Html,
        context.temp_allocator,
    )

    return response, nil
}

UserError :: enum {
    DatabaseError,
    ValidationError,
}

main :: proc() {
    context.logger = log.create_console_logger(.Info)
    defer log.destroy_console_logger(context.logger)

    endpoint := net.Endpoint {
        address = net.IP4_Address{127, 0, 0, 1},
        port    = 8080,
    }

    server: fjord.Server(UserError)
    fjord.server_init(&server, endpoint, context.allocator)
    defer fjord.server_destroy(&server)

    fjord.server_add_route(&server, .GET, {"hello", ":name"}, hello_handler)
    fjord.server_add_route(&server, .GET, {"users", ":id", "posts", ":post_id"}, user_post_handler)

    log.infof("Server listening on http://127.0.0.1:%d", endpoint.port)
    fjord.server_listen_and_serve(&server)
}

Dev

Run the test suite to check functionality, curl is a required dependency for the test suite to work.

odin test .