HTTP-запрос в Iron представлен как высокоуровневая абстракция над входящим потоком Node.js, скрывающая детали транспорта и предоставляющая унифицированную структуру данных. Внутри этот объект формируется поэтапно: от сырых TCP-данных до полностью разобранного представления с маршрутизацией, заголовками, телом и метаданными запроса.
Внутренне объект запроса можно разделить на несколько логических слоёв:
Каждый из этих слоёв формируется в разные моменты жизненного цикла запроса, что позволяет минимизировать накладные расходы до момента реальной необходимости данных.
На самом нижнем уровне запрос опирается на поток, аналогичный
http.IncomingMessage. На этом этапе доступны только базовые
данные:
GET, POST, PUT и
т.д.)Эти данные не интерпретируются, а лишь фиксируются как исходное состояние запроса. Важно, что на этом уровне тело запроса ещё не прочитано и не буферизовано.
После первичной фиксации данных происходит разбор URL. Внутри Iron URL преобразуется в структурированный объект:
pathname — путь без query-параметровqueryString — строковая часть после ?query — объект разобранных параметровhash — фрагмент (если применимо)При этом разбор query часто реализуется лениво. Это означает, что
строка параметров хранится в исходном виде до первого обращения к
request.query.
Подобный подход снижает нагрузку на парсер в случаях, когда параметры запроса не используются обработчиком.
Заголовки в Iron представлены не как сырый объект Node.js, а как нормализованная структура:
content-type)Внутри используется структура, близкая к Map, что
позволяет:
Дополнительно часто формируется кэш популярных заголовков:
content-typecontent-lengthauthorizationuser-agentЭто ускоряет доступ к наиболее часто используемым данным без повторного поиска в общей карте.
Тело запроса не загружается автоматически. Вместо этого создаётся потоковая обёртка, которая может быть преобразована в зависимости от типа контента.
Внутренне тело представлено в виде одного из вариантов:
Buffer (для бинарных данных)Процесс обработки выглядит следующим образом:
Парсинг JSON, form-data или urlencoded данных обычно выполняется
только при первом обращении к request.body.
Одним из ключевых элементов внутренней структуры является определение
парсера тела запроса. Оно базируется на заголовке
Content-Type.
Примеры внутреннего сопоставления:
application/json → JSON parserapplication/x-www-form-urlencoded → URL encoded
parsermultipart/form-data → multipart parserЭто сопоставление хранится в виде таблицы стратегий. При необходимости система может быть расширена пользовательскими парсерами, которые регистрируются в реестре middleware.
После прохождения слоя маршрутизации объект запроса дополняется параметрами пути.
Если маршрут задан как:
/users/:id/posts/:postId
то внутри запроса появляется структура:
params.idparams.postIdЭти значения извлекаются на этапе сопоставления маршрута и кэшируются внутри объекта запроса, чтобы исключить повторный парсинг URL.
Помимо стандартных HTTP-данных, объект запроса содержит набор вычисляемых метаданных:
protocol (http/https)secure (булевый флаг)hostnameip (IP клиента)ips (цепочка прокси)subdomainsОпределение IP-адреса может учитывать заголовки:
x-forwarded-forx-real-ipПри этом порядок доверенных прокси играет ключевую роль, так как влияет на корректность вычисления реального клиента.
Одной из важных особенностей внутренней структуры является ленивое вычисление свойств. Это означает, что многие поля создаются только при первом обращении:
request.bodyrequest.queryrequest.cookiesrequest.ipПосле первого вычисления результат сохраняется в кеше внутри объекта запроса. Повторные обращения не запускают повторный парсинг.
Такой подход снижает нагрузку при больших потоках запросов, особенно в API с минимальным использованием данных запроса.
Cookies не извлекаются автоматически в базовой структуре. При первом обращении к cookie-объекту выполняется:
cookie;Внутренне cookies часто хранятся отдельно от основных заголовков, чтобы ускорить доступ и избежать повторного парсинга строки.
После инициализации объект запроса обычно считается частично неизменяемым:
Однако некоторые поля могут дополняться middleware:
request.state — пользовательское состояниеrequest.context — контекст выполненияЭти структуры отделены от системных данных, чтобы избежать конфликтов между библиотечным и пользовательским кодом.
Если тело запроса не буферизуется заранее, оно может быть обработано как поток. В этом режиме:
Это особенно важно для больших файлов и streaming API, где полная загрузка тела в память недопустима.
Внутренне поток оборачивается в контролируемый интерфейс, который позволяет:
Ошибки, возникающие при обработке запроса, сохраняются внутри объекта в стандартизированном виде:
Каждая ошибка имеет:
Это позволяет middleware принимать решения без необходимости повторного анализа входных данных.
После прохождения всех этапов объект запроса представляет собой объединённую структуру:
Эта структура формируется инкрементально, что позволяет Iron эффективно обрабатывать большое количество параллельных запросов без избыточной нагрузки на парсинг и память.