99 lines
2.6 KiB
Markdown
99 lines
2.6 KiB
Markdown
# 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
|
|
|
|
```odin
|
|
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.
|
|
```bash
|
|
odin test .
|
|
```
|