Socat - http-сервер для бедняков

Последние несколько часов я ломал себе голову, пытаясь построить http-сервер бедняка с помощью socat. Не спрашивайте почему и не предлагайте альтернативы. Мне нужно сделать это в чистом bash. Итак, я запускаю socat следующим образом:

socat -v TCP-LISTEN:1234,reuseaddr,fork SYSTEM:./httpd.sh

Предполагается, что httpd.sh читает http-запрос, анализирует его и затем отправляет ответ.

например GET /index.html выведет Index!, а GET /random выведет случайное число.

У меня проблема с чтением всего http-запроса. Рассмотрим следующий код, используемый для чтения каждой строки http-запроса:

while read -r LINE
do
    echo "$LINE" 
done

Обычно он должен возвращать запрос в браузер. Проблема в том, что после того, как я открываю 127.0.0.1:1234, он просто зависает в ожидании чего-то. Если я CTRL + C socat, соединение закрывается, и ответ отображается в браузере. Я думаю, что цикл while продолжается вечно, что предотвращает передачу ответа.

Если я использую код ниже:

while read -r LINE
do
    echo "$LINE" 
    [ -z "$LINE" ] && break
done

цикл while прерывается, и браузер больше не зависает. Кажется хорошим решением. Но... в случае запроса POST данные POST не записываются, потому что разрыв происходит сразу после заголовков (пустая строка)...

POST /index.html HTTP/1.0
User-Agent: Firefox
Content-Type: application/x-www-form-urlencoded

parameter1=test

Что я могу сделать, чтобы прочитать весь HTTP-запрос через сценарий оболочки, обработать его и отправить ответ без каких-либо зависаний?

ИЗМЕНИТЬ:

Вот кое-что, что, я думаю, может содержать ответ. Если я запускаю эту команду:

socat TCP4-LISTEN:1234,reuseaddr,fork,crlf SYSTEM:"echo hello world"

Все работает нормально, всегда выводится hello world.

Как Socat узнает, когда заканчивается HTTP-запрос?


person mike123    schedule 09.04.2021    source источник
comment
Проверьте gist.github.com/robspassky/1959319. Он основан на inetd, но inetd IIRC взаимодействует со своими сценариями так же, как и socat в вашем примере. Поиск решений на основе inetd может дать некоторую информацию.   -  person Rory Browne    schedule 09.04.2021
comment
Спасибо, но в примере он анализирует только GET-запросы, так же как и проблема.   -  person mike123    schedule 09.04.2021


Ответы (2)


Что я могу сделать, чтобы прочитать весь HTTP-запрос через сценарий оболочки, обработать его и отправить ответ без каких-либо зависаний?

Пока вы пишете, у вас уже есть решение для GET; в случае запроса POST вам просто нужно прочитать еще одну строку (несколько значений данных разделены & в одной строке). После отправки ответа вы должны выйти из httpd.sh или хотя бы закрыть его вывод.

Как Socat узнает, когда заканчивается HTTP-запрос?

socat знает, что ответ закончился, когда канал данных от echo закрывается после завершения этого процесса.

person Armali    schedule 09.04.2021

Вы не можете прочитать запрос построчно. HTTP-запросы могут содержать разрывы строк. Вам нужно прочитать весь запрос и проанализировать его.

Для запросов GET или запросов Head вам нужны только заголовки, поэтому вы можете прочитать только одну строку.

Для сообщений вам нужно прочитать либо количество байтов, указанное в заголовке длины содержимого, либо до тех пор, пока вы не получите EOF.

Достаточно сказать, что ваш сценарий становится более сложным.

person Ricardo    schedule 09.04.2021
comment
1. Что вы подразумеваете под пока не получите EOF. ? - person mike123; 09.04.2021