Skip to content

HTTP-запросы

HTTP-запросы обрабатываются через контекст httpctx_t, который предоставляет доступ к объектам request и response.

Базовая структура обработчика

c
#include "http.h"

void my_handler(httpctx_t* ctx) {
    // ctx->request — объект запроса
    // ctx->response — объект ответа

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

Параметры GET-запроса

Параметры строки запроса извлекаются функциями из 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");
}

Параметры маршрута

Динамические параметры из URL также доступны через функции 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 содержит значение из URL, например "123" для /api/users/123
    if (!ok) {
        ctx->response->send_data(ctx->response, "Invalid id");
    }
}

Данные POST/PUT/PATCH запросов

Данные тела запроса доступны через методы payload:

Получение всего тела запроса

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);
}

Получение поля по ключу

Для multipart/form-data и 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;
    }

    // Обработка данных...

    free(email);
    free(password);
}

Получение JSON из тела запроса

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);
}

Подробнее о работе с payload: Получение данных от клиента

HTTP-метод запроса

Текущий метод доступен через ctx->request->method:

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

URL запроса

Свойства для работы с URL:

СвойствоОписаниеПример
uriПолный URI с параметрами/users?id=100
pathПуть без параметров/users
extРасширение файлаhtml
uri_lengthДлина URI
path_lengthДлина пути
ext_lengthДлина расширения
c
void handler(httpctx_t* ctx) {
    // Проверка длины URI
    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-заголовки

Получение заголовков запроса:

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) {
        // Проверка авторизации...
    }
}

Чтение cookie из запроса:

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;
    }

    // Валидация токена...
}

Подробнее: Cookie

Соединение с базой данных

Доступ к базам данных через контекст:

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;
    }

    // Выполнение запросов...
    dbresult_free(result);
}

Подробнее: База данных

Выпущено под лицензией MIT.