Skip to content

HTTP requests

HTTP requests are processed through the httpctx_t context, which provides access to request and response objects.

Basic handler structure

c
#include "http.h"

void my_handler(httpctx_t* ctx) {
    // ctx->request — request object
    // ctx->response — response object

    ctx->response->send_data(ctx->response, "Hello World");
}

GET request parameters

Query string parameters are extracted using functions from query.h:

c
#include "query.h"

void get_users(httpctx_t* ctx) {
    int ok_id = 0, ok_name = 0;
    const char* id = query_param_char(ctx->request, "id", &ok_id);
    const char* name = query_param_char(ctx->request, "name", &ok_name);

    if (ok_id && ok_name) {
        ctx->response->send_data(ctx->response, id);
        return;
    }

    ctx->response->send_data(ctx->response, "Missing parameters");
}

Route parameters

Dynamic URL parameters are also available through functions from query.h:

json
// config.json
"/api/users/{id|\\d+}": {
    "GET": { "file": "handlers/libapi.so", "function": "get_user" }
}
c
#include "query.h"

void get_user(httpctx_t* ctx) {
    int ok = 0;
    const char* id = query_param_char(ctx->request, "id", &ok);
    // id contains the value from URL, e.g. "123" for /api/users/123
    if (!ok) {
        ctx->response->send_data(ctx->response, "Invalid id");
    }
}

POST/PUT/PATCH request data

Request body data is available through payload methods:

Getting the entire request body

c
void post_data(httpctx_t* ctx) {
    char* payload = ctx->request->get_payload(ctx->request);

    if (!payload) {
        ctx->response->send_data(ctx->response, "No payload");
        return;
    }

    ctx->response->send_data(ctx->response, payload);
    free(payload);
}

Getting a field by key

For multipart/form-data and application/x-www-form-urlencoded:

c
void post_form(httpctx_t* ctx) {
    char* email = ctx->request->get_payloadf(ctx->request, "email");
    char* password = ctx->request->get_payloadf(ctx->request, "password");

    if (!email || !password) {
        ctx->response->send_data(ctx->response, "Missing fields");
        if (email) free(email);
        if (password) free(password);
        return;
    }

    // Process data...

    free(email);
    free(password);
}

Getting JSON from request body

c
#include "json.h"

void post_json(httpctx_t* ctx) {
    json_doc_t* doc = ctx->request->get_payload_json(ctx->request);

    if (!json_ok(doc)) {
        ctx->response->send_data(ctx->response, "Invalid JSON");
        json_free(doc);
        return;
    }

    json_token_t* root = json_root(doc);
    json_token_t* name = json_object_get(root, "name");

    if (name && json_is_string(name)) {
        ctx->response->send_data(ctx->response, json_string(name));
    }

    json_free(doc);
}

More about working with payload: Getting data from the client

HTTP request method

The current method is available through ctx->request->method:

c
void handler(httpctx_t* ctx) {
    switch (ctx->request->method) {
        case ROUTE_GET:
            // GET request
            break;
        case ROUTE_POST:
            // POST request
            break;
        case ROUTE_PUT:
            // PUT request
            break;
        case ROUTE_PATCH:
            // PATCH request
            break;
        case ROUTE_DELETE:
            // DELETE request
            break;
        case ROUTE_OPTIONS:
            // OPTIONS request
            break;
    }
}

Request URL

Properties for working with URLs:

PropertyDescriptionExample
uriFull URI with parameters/users?id=100
pathPath without parameters/users
extFile extensionhtml
uri_lengthURI length
path_lengthPath length
ext_lengthExtension length
c
void handler(httpctx_t* ctx) {
    // Check URI length
    if (ctx->request->uri_length > 4096) {
        ctx->response->send_default(ctx->response, 414); // URI Too Long
        return;
    }

    ctx->response->send_data(ctx->response, ctx->request->path);
}

HTTP headers

Getting request headers:

c
void handler(httpctx_t* ctx) {
    http_header_t* host = ctx->request->get_header(ctx->request, "Host");
    http_header_t* auth = ctx->request->get_header(ctx->request, "Authorization");

    if (host) {
        printf("Host: %s\n", host->value);
    }

    if (auth) {
        // Check authorization...
    }
}

Reading cookies from request:

c
void handler(httpctx_t* ctx) {
    const char* token = ctx->request->get_cookie(ctx->request, "session_token");

    if (!token) {
        ctx->response->send_data(ctx->response, "Not authorized");
        return;
    }

    // Validate token...
}

More details: Cookie

Database connection

Accessing databases through context:

c
#include "db.h"

void handler(httpctx_t* ctx) {
    dbresult_t* result = dbquery("postgresql", "SELECT 1", NULL);

    if (!dbresult_ok(result)) {
        ctx->response->send_data(ctx->response, "Database not available");
        dbresult_free(result);
        return;
    }

    // Execute queries...
    dbresult_free(result);
}

More details: Database

Released under the MIT License.