Обработчики CONNECT в Node.js должны сохранять буфер head
Работайте с сокетом CONNECT и буфером head в Node на границе HTTP и туннеля, сохраняя байты, уже прочитанные за пределами заголовков.
HTTP-сервер Node обрабатывает обычный прокси-запрос через свой callback запроса. CONNECT идёт другим путём: сервер выдаёт connect вместе с запросом, клиентским сокетом и буфером head.
Это событие — передача между разбором HTTP и туннелем. Обычного объекта ServerResponse, который можно было бы дальше использовать для туннельного трафика, нет.
| Аргумент | Что он несёт |
|---|---|
req | Запрос CONNECT, включая его целевой авторитет и заголовки |
clientSocket | Соединение обратно к клиенту |
head | Данные туннеля, которые Node уже прочитал за пределами HTTP-заголовков, возможно пустые |
Завершите решение HTTP до передачи байтов
Проверьте запрошенные хост и порт, примените политику доступа и аутентификации прокси и установите восходящее соединение. CONNECT определяет авторитет вида service.example:443; разбирайте эту форму с учётом авторитетов IPv6, а не делите вслепую по каждому двоеточию.
Когда туннель принят, отправьте успешный HTTP-ответ, а затем завершающую пустую строку. После этого передайте любые байты head вверх по потоку, прежде чем продолжать с последующими байтами из клиентского сокета. Подключение нового обработчика данных не может вернуть буфер, который уже был отдельно передан обработчику.
Официальный пример туннелирования в Node выполняет эту передачу с помощью serverSocket.write(head) перед соединением двух направлений потока. Его небольшой пример иллюстрирует переход; развёрнутому прокси также нужны ограниченные попытки подключения, контроль доступа и управление жизненным циклом.
После успеха байты принадлежат протоколу сервиса
Успешный ответ CONNECT превращает соединение в поток байтов. Если цель — сайт HTTPS, его обмен TLS происходит внутри этого потока. Само туннелирование не требует, чтобы прокси выдавал заменяющий сертификат сайта.
До принятия CONNECT ошибка HTTP может объяснить причину отказа. После принятия запись HTTP 500 в поток внедрила бы байты в туннельный протокол. Вместо этого завершайте или уничтожайте соответствующие соединения при последующих сбоях.
Соедините оба направления с помощью обработка потока с учётом обратного давления и решите, как события end, error и close завершают партнёра. Сохраняйте исходный буфер head как часть той же модели владения; это данные приложения, а не лишние HTTP-заголовки, которые можно выбросить.