Skip to content
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
155 changes: 155 additions & 0 deletions docs/api/API_REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,161 @@ uv_run(loop, UV_RUN_DEFAULT);
uvhttp_server_free(server);
```

## Server API (reference)

### uvhttp_server_new_with_loop

```c
uvhttp_error_t uvhttp_server_new_with_loop(uvhttp_server_t** server);
```

Creates a server that **owns** its event loop (released by `uvhttp_server_free`).
Prefer `uvhttp_server_new(loop, &server)` unless the server must outlive the
caller's loop.

**Return Value**: `UVHTTP_OK`, `UVHTTP_ERROR_INVALID_PARAM` (NULL `server`), or
`UVHTTP_ERROR_OUT_OF_MEMORY`.

### uvhttp_server_enable_tls / uvhttp_server_disable_tls

```c
uvhttp_error_t uvhttp_server_enable_tls(uvhttp_server_t* server,
uvhttp_tls_context_t* tls_ctx);
uvhttp_error_t uvhttp_server_disable_tls(uvhttp_server_t* server);
```

Hands a TLS context to the server (**ownership transfers** - the server frees it,
like `uvhttp_server_take_router`). Requires `BUILD_WITH_HTTPS`.

### uvhttp_server_set_handler

```c
uvhttp_error_t uvhttp_server_set_handler(uvhttp_server_t* server,
uvhttp_request_handler_t handler);
```

Sets a single catch-all handler for every request. Mutually exclusive with a
router: when a router is installed it wins.

### uvhttp_server_take_context

```c
uvhttp_error_t uvhttp_server_take_context(uvhttp_server_t* server,
struct uvhttp_context* context);
```

Hands a context to the server (**ownership transfers**, no detach, one context
per server). See `uvhttp_server_take_router` for the same rules.

### uvhttp_server_enable_health_check

```c
uvhttp_error_t uvhttp_server_enable_health_check(uvhttp_server_t* server,
const char* path);
```

Registers a `{"status":"ok"}` handler at `path` on the server's router,
creating a router first if the server has none.

## Builder API

The builder entry point (`uvhttp_server_create`) creates server + router +
config, starts listening, and returns a `uvhttp_server_builder_t*` for
chaining. It has the same all-or-nothing contract as
`uvhttp_server_listen_routes`: on any failure the out pointer is NULL and
nothing is allocated.

The builder is a **view, not an owner**: `server`, `router` and `config`
handles are exposed for convenience, but `uvhttp_server_free` releases all
three. Tear down with `uvhttp_server_simple_free()` (server + builder) - never
per-field.

### uvhttp_server_create

```c
uvhttp_error_t uvhttp_server_create(uv_loop_t* loop, const char* host,
int port,
uvhttp_server_builder_t** server);
```

**Parameters**:
- `loop`: Initialized event loop
- `host`: Listen address (e.g. "0.0.0.0")
- `port`: Listen port
- `server`: Out pointer; NULL on failure

**Return Value** (v2.10: the real cause is propagated, not collapsed into
`SERVER_LISTEN`):
- `UVHTTP_OK`: Success - fully listening builder
- `UVHTTP_ERROR_INVALID_PARAM`: NULL `loop`/`host`/`server`
- `UVHTTP_ERROR_OUT_OF_MEMORY`: any allocation failed
- `UVHTTP_ERROR_SERVER_LISTEN`: bind or listen syscall failed

**Example**:
```c
uvhttp_server_builder_t* builder = NULL;
uvhttp_error_t result =
uvhttp_server_create(loop, "0.0.0.0", 8080, &builder);
if (result != UVHTTP_OK) {
/* nothing was allocated; nothing to clean up */
return 1;
}

/* Chaining: routes plus the one config knob that has an effect. */
uvhttp_get(builder, "/", hello_handler);
uvhttp_get(builder, "/health", health_handler);
uvhttp_set_max_connections(builder, 1000);

uvhttp_server_run(builder);
uvhttp_server_simple_free(builder);
```

### uvhttp_get / uvhttp_post / uvhttp_put / uvhttp_delete / uvhttp_any

```c
uvhttp_server_builder_t* uvhttp_get(uvhttp_server_builder_t* server,
const char* path,
uvhttp_request_handler_t handler);
```

Registers a route on the builder's router; the four siblings differ only in
method. Returns the builder for chaining (NULL in, NULL out).

Registration failures are **logged, not returned** - the chain continues, so
verify the path/handler you passed rather than the return value.

### uvhttp_set_max_connections

```c
uvhttp_server_builder_t* uvhttp_set_max_connections(
uvhttp_server_builder_t* server, int max_conn);
```

The connection cap, and the only builder config knob with an effect. Silent
no-op on NULL or on a builder without a config.

### uvhttp_server_run / uvhttp_server_stop_simple / uvhttp_server_simple_free

```c
int uvhttp_server_run(uvhttp_server_builder_t* server);
void uvhttp_server_stop_simple(uvhttp_server_builder_t* server);
void uvhttp_server_simple_free(uvhttp_server_builder_t* server);
```

Run the loop until stopped; stop accepting connections; release the builder
(and, through it, the server, router and config). All three are NULL-tolerant.

### uvhttp_serve

```c
int uvhttp_serve(uv_loop_t* loop, const char* host, int port);
```

One-key start for scripts and demos: `uvhttp_server_create` + a `/` default
route + run + free. Validates `port` in 1..65535; a NULL `host` is treated as
0.0.0.0 with a warning (the listen call then fails, so a NULL host is an
error, not a default).

## Router API

### uvhttp_router_new
Expand Down
64 changes: 64 additions & 0 deletions docs/spec/server-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,70 @@ connection management.
- `UVHTTP_ERROR_SERVER_LISTEN`: bind or listen syscall failed
- **Thread safety**: Not thread-safe. Must be called from the event loop thread.

### uvhttp_server_new_with_loop
- **Signature**: `uvhttp_error_t uvhttp_server_new_with_loop(uvhttp_server_t** server)`
- **Purpose**: Create a server that **owns** its event loop (`uv_loop_new` internally; released by `uvhttp_server_free`).
- **Preconditions**: `server` must be a non-NULL out pointer.
- **Postconditions**: `*server` is a valid, non-listening server with `config == NULL` and `context == NULL` (no context is created).
- **Error conditions**:
- `UVHTTP_ERROR_INVALID_PARAM`: `server` is NULL
- `UVHTTP_ERROR_OUT_OF_MEMORY`: server or loop allocation failed
- **Thread safety**: Not thread-safe.
- **Note**: Prefer `uvhttp_server_new(loop, &server)` - the caller-owns-the-loop shape is what most embedding code already does. This entry exists for the rare case where the server should outlive the caller's loop.

### uvhttp_server_create
- **Signature**: `uvhttp_error_t uvhttp_server_create(uv_loop_t* loop, const char* host, int port, uvhttp_server_builder_t** server)`
- **Purpose**: Builder construction: create server + router + config, start listening, and return a **builder** for chaining routes and the one tunable config knob.
- **Preconditions**: `loop`, `host`, and `server` must be non-NULL.
- **Postconditions**: On success, `*server` is a fully listening builder. On **any** failure, `*server` is NULL and nothing is allocated - the caller has no rollback to write (v2.10: the out-param is established once at function entry instead of per branch).
- **Ownership**: the builder is a **view, not an owner**. `server`/`router`/`config` handles are exposed for convenience; `uvhttp_server_free` releases all three. Dropping a builder is therefore always `uvhttp_server_simple_free()` (server + builder), never a per-field teardown.
- **Error conditions** (v2.10: propagated, not collapsed - a caller mistake and a runtime failure need different remediation):
- `UVHTTP_ERROR_INVALID_PARAM`: `loop`, `host`, or `server` is NULL
- `UVHTTP_ERROR_OUT_OF_MEMORY`: any allocation failed
- `UVHTTP_ERROR_SERVER_LISTEN`: bind or listen syscall failed (occupied port)
- **Thread safety**: Not thread-safe. Must be called from the event loop thread.

### uvhttp_server_run / uvhttp_server_stop_simple / uvhttp_server_simple_free
- **Signatures**: `int uvhttp_server_run(uvhttp_server_builder_t* server)` / `void uvhttp_server_stop_simple(uvhttp_server_builder_t* server)` / `void uvhttp_server_simple_free(uvhttp_server_builder_t* server)`
- **Purpose**: Run the loop until stopped; stop accepting connections; release the builder (and, through it, the server, router and config).
- **Preconditions**: `server` must be a builder from `uvhttp_server_create` (NULL-tolerant throughout: each function no-ops on NULL).
- **Postconditions**: `simple_free` leaves nothing allocated; the builder owns nothing, so there is no double-release hazard when the caller also holds handles from the builder struct.
- **Thread safety**: Not thread-safe. `run` blocks the calling thread.

### uvhttp_get / uvhttp_post / uvhttp_put / uvhttp_delete / uvhttp_any
- **Signature**: `uvhttp_server_builder_t* uvhttp_<method>(uvhttp_server_builder_t* server, const char* path, uvhttp_request_handler_t handler)`
- **Purpose**: Register a route on the builder's router and return the builder (chaining).
- **Preconditions**: `server`, `path`, and `handler` must be non-NULL; `path` must match the router's rules (no query string, `:param` supported, length < `MAX_ROUTE_PATH_LEN`).
- **Postconditions**: `server->router` contains the route. The builder pointer is returned unchanged for chaining, so a NULL argument silently returns NULL.
- **Error conditions**: registration failure is **logged, not returned** - the chain continues, so the caller must verify the path/handler it passed rather than the return value.
- **Thread safety**: Not thread-safe.

### uvhttp_set_max_connections
- **Signature**: `uvhttp_server_builder_t* uvhttp_set_max_connections(uvhttp_server_builder_t* server, int max_conn)`
- **Purpose**: Set the connection cap - **the only builder config knob that has an effect**. It writes `config->max_connections`, which the connection path reads.
- **Preconditions**: `server` must be a builder from `uvhttp_server_create` (it must have a config).
- **Postconditions**: `config->max_conn == max_conn`. Returns the builder for chaining; on NULL it returns NULL.
- **Error conditions**: none reported - a builder without a config (e.g. from `uvhttp_server_new`) makes this a silent no-op, as does NULL.
- **History**: `uvhttp_set_timeout()` and `uvhttp_set_max_body_size()` were removed in v2.10 (they wrote config fields no execution path read); see docs/spec/config-api.md.
- **Thread safety**: Not thread-safe.

### uvhttp_serve
- **Signature**: `int uvhttp_serve(uv_loop_t* loop, const char* host, int port)`
- **Purpose**: One-key start: `uvhttp_server_create` + a `/` default route + run + free. For scripts and demos.
- **Preconditions**: `loop` non-NULL, `port` in 1..65535. `host` may be NULL (treated as 0.0.0.0 with a warning).
- **Postconditions**: returns when the loop stops; the server is freed before returning.
- **Error conditions**: `UVHTTP_ERROR_INVALID_PARAM` (NULL loop, out-of-range port, or NULL host - which makes the listen call fail) or whatever `uvhttp_server_create` propagated; 0 on a clean loop exit.
- **Thread safety**: Not thread-safe. Blocks the calling thread.

### uvhttp_server_enable_health_check
- **Signature**: `uvhttp_error_t uvhttp_server_enable_health_check(uvhttp_server_t* server, const char* path)`
- **Purpose**: Register a `{"status":"ok"}` handler at `path` for load-balancer probes.
- **Preconditions**: `server` and `path` must be non-NULL. A router is created if the server has none.
- **Postconditions**: `GET path` returns 200 `application/json` `{"status":"ok"}`.
- **Error conditions**:
- `UVHTTP_ERROR_INVALID_PARAM`: `server` or `path` is NULL, or route registration failed
- **Thread safety**: Not thread-safe.

### uvhttp_server_enable_tls / uvhttp_server_disable_tls
- **Signature**: `uvhttp_error_t uvhttp_server_enable_tls(uvhttp_server_t* server, uvhttp_tls_context_t* tls_ctx)` / `uvhttp_error_t uvhttp_server_disable_tls(uvhttp_server_t* server)`
- **Purpose**: Enable or disable TLS on the server
Expand Down
1 change: 1 addition & 0 deletions include/uvhttp_request.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ UVHTTP_STATIC_ASSERT(offsetof(uvhttp_request_t, headers) >= 64,
"headers array should be after first 64 bytes");

/* API functions */
uvhttp_error_t uvhttp_request_init(uvhttp_request_t* request, uv_tcp_t* client);
const char* uvhttp_request_get_method(uvhttp_request_t* request);
const char* uvhttp_request_get_url(uvhttp_request_t* request);
void uvhttp_request_free(uvhttp_request_t* request);
Expand Down
4 changes: 0 additions & 4 deletions include/uvhttp_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -607,10 +607,6 @@ void uvhttp_server_ws_update_activity(uvhttp_server_t* server,
uvhttp_ws_connection_t* ws_conn);
#endif

/* internalFunction */
uvhttp_error_t uvhttp_request_init(uvhttp_request_t* request, uv_tcp_t* client);
void uvhttp_request_cleanup(uvhttp_request_t* request);

/* TLSFunction (whenDisable) */
/* uvhttp_error_t uvhttp_tls_init(void); */
/* void uvhttp_tls_context_free(uvhttp_tls_context_t* ctx); */
Expand Down
Loading