Основы HTTP: структура-представление и трёхзначный возврат
RequestProc получает не объект-обёртку, а набор «можно сразу действовать» нативных указателей xrt. Глава дорисовывает карту этого представления — следующие четыре главы работают на ней.
Обзор
14.1 Введение
Для HTTP-бизнеса нужны три вещи: знать, что за запрос (метод, путь, заголовки, тело), знать, куда писать ответ (транспорт) и знать, кто забирает управление после вас. Большинство фреймворков мнут всё это в объект Request/Response, меняя абстракцию на удобство; XServer выдаёт три вещи раздельно — шесть полей XS_HttpReq и есть их адреса.
14.2 XS_HttpReq по полям
typedef struct {
xnetstream* tcp; /* ровно один из tcp/tls не пуст: голый транспорт */
xtlsstream* tls; /* применим весь потоковый/отправочный API xrt */
const xhttp1head* head; /* вкл. MethodCode; представление валидно в колбэке */
xhttp1body* body; /* автомат кадрирования: фикс / chunked / close */
const XS_HostInfo* host;
XS_ServerInfo* server;
} XS_HttpReq;
| Поле | Назначение | Использование здесь |
|---|---|---|
tcp / tls | выход ответа | отправка байтов ответа (гл. 15) |
head | личность запроса | MethodCode, путь, представления полей (14.3) |
body | тело запроса | инкрементальное чтение (гл. 16) |
host / server | принадлежность | топология, ручки Custom |
Почему нет поля Response? — потому что ответ не объект, а поток байтов, который вы пишете в транспорт. В этом предельность «нуля обёрток»: нет скрытого буфера ответа — значит, нет и вопросов класса «когда фреймворк делает flush».
14.3 Чтение заголовков запроса
static XS_RequestResult RequestProc(XS_HttpReq* pReq)
{
/* метод: битовая маска — одновременно и метод, и элемент множества (ref-enums) */
if ( pReq->head->MethodCode == XHTTP_METHOD_GET ) { ... }
/* представления пути и полей: xstrview = указатель + длина, валидны в колбэке */
/* конкретные API доступа (поиск полей / разбор пути) — в xrt · http1 */
return XS_FALLBACK;
}
Два железных правила чтения головы: первое — представления полей head действительны только в стеке данного колбэка — XServer копирует заголовок запроса на фазе PinHead, чтобы помешать переиспользованию ring-буфера, но после смены поколения/конца запроса они всё равно истекают; второе — не сравнивайте пути C-строковыми функциями: у представлений есть длина, сравнивайте по длине (инструменты xrtStrView).
14.4 Момент вызова и потоки
- По разу на запрос; на keep-alive-соединении вызывается на каждый запрос
- Конкурентность workers — RequestProc обязан быть реентерабельным (без изменяемых межзапросных статиков или с собственной блокировкой)
- Между драйвером и скриптом действует перекрёстная сверка потреблённых байтов: расхождение заявленного с фактическим в сети рвёт соединение — скрипт рассматривается как недоверенная граница
14.5 Контракт
- Заимствование: все шесть полей действительны внутри колбэка; значения можно копировать, указатели нельзя.
- Трёхзначность: перед XS_OK ответ дописан; один записанный байт запрещает FALLBACK; после TAKEOVER драйвер отходит.
- Конкурентность: RequestProc исполняется конкурентно на workers — реентерабельность есть жёсткое требование.
Частые ошибки
- Симптом
- Случайные ошибки определения пути, особенно со строкой запроса или буфером без нуля в конце.
- Причина
- xstrview — не C-строка: NUL-терминатора может не быть, авторитетна длина.
if ( strcmp(pPath, "/api") == 0 )/* сравнение по длине представления (инструменты xrtStrView) */- Симптом
- Под конкурентностью сбивающиеся счётчики, случайные падения.
- Причина
- Забыта конкурентность workers — статические переменные читаются и пишутся несколькими запросами одновременно.
Упражнения
Напишите RequestProc: GET печатает "GET", POST печатает "POST", остальное возвращает XS_FALLBACK.
Считайте обработанные запросы (подсказка: атомики, семейство xrtAtomic).
Сохраните указатель представления head в глобальную и прочитайте на следующем запросе — пронаблюдайте и объясните; затем перепишите на копирование внутри колбэка.
Итоги
| Тезис | Вывод |
|---|---|
| Структура-представление | tcp/tls (выход) + head (личность) + body (тело) + host/server (принадлежность) |
| Нет объекта Response | ответ — поток байтов в транспорт (гл. 15) |
| Правила чтения головы | представления валидны в колбэке; сравнение по длине, не как C-строки |
| Конкурентность | реентерабельность на workers; сверка потребления с сетью |
- справочник xrt · http1 — полный набор представлений полей xhttp1head и API поиска заголовков
- справочник xrt · string — сравнение представлений и безопасные строковые инструменты