Я пытаюсь написать простой обработчик для веб-перехватчика с использованием xinetd и bash. У меня есть тривиальный случай, когда я работаю с этой конфигурацией для xinetd:
service github-hooks
{
port = 61000
socket_type = stream
protocol = tcp
wait = no
user = ubuntu
server = /home/ubuntu/github-hooks.sh
}
и этим сценарием bash:
#!/bin/bash
echo -e "HTTP/1.1 200 OK"
, теперь я хочу прочитать данные сообщения, которые отправляются в веб-перехватчике, чтобы я мог сделать что-то более интересное, что всегда возвращается 200.
Как мне прочитать данные сообщения из моего сценария bash?
Я пробовал:
while read line; do
echo "$line" >> /home/ubuntu/test
done < /dev/stdin
, но у меня это не работает.
Изменить
Благодаря предложенному ниже предложению я остановил xinetd
и использовал nc
, чтобы посмотреть, какие необработанные данные передаются по сети:
$nc -l 61000
, и получил следующее:
POST / HTTP/1.1
Host: <snip>:61000
Accept: */*
User-Agent: GitHub-Hookshot/375c44e
X-GitHub-Event: pull_request
X-GitHub-Delivery: 2dc1fb00-1c8e-11e6-9955-64afafb6ce32
content-type: application/json
X-Hub-Signature: sha1=45afd85b7d4312fa8ac4c56638e8e9699e2ddb36
Content-Length: 20558
{"action":"opened","number":116,"pull_request": <snip>
Итак, данные отправляются. Теперь, зная, что отправлено ровно 11 строк, я прочитал ровно 11 строк:
for i in {0..10}
do
read line
echo "$line" >> /home/ubuntu/test
done
И я получил тот же результат (большой успех: )
POST / HTTP/1.1
Host: <snip>:61000
Accept: */*
User-Agent: GitHub-Hookshot/375c44e
X-GitHub-Event: pull_request
X-GitHub-Delivery: 2dc1fb00-1c8e-11e6-9955-64afafb6ce32
content-type: application/json
X-Hub-Signature: sha1=45afd85b7d4312fa8ac4c56638e8e9699e2ddb36
Content-Length: 20558
{"action":"opened","number":116,"pull_request": <snip>
Может быть, мне просто прочитать 9 строк, а затем использовать параметр Content-Length
для чтения остальных? Я до сих пор не совсем понимаю, что происходит, поэтому любая информация будет очень полезной.
Хорошо,Я так и не понял, как читать, пока есть ввод, но я заметил, что в заголовке есть длина. Итак, я анализирую длину, а затем читаю это количество символов:
#!/bin/bash
for i in {1..9}
do
read line
done
array=(${line})
length=${array[1]}
read line
read -n ${length:0:-1} line
echo "$line" >> /home/ubuntu/test
echo -e "HTTP/1.1 200 OK"
И теперь у меня есть почтовые данные, которые отправляет github.
Для чтения стандартных почтовых данных для http-запроса xinetd программа просто читает стандартный ввод.
Я написал сценарий bash, который читает и анализирует заголовки http, переданные через стандартный ввод . Полезно при вызове из xinetd. Я создал это как отправную точку для тех, кто хочет создать службу xinetd, которая может распознавать HTTP-запросы, подобные REST. https://github.com/rglaue/xinetd_bash_http_service
Но по сути, чтение ввода HTTP (Заголовки и данные POST) в службе xinetd выглядит примерно так:
# Read HTTP Headers, line by line
# We're looking for the Content-Length HTTP header
: ${HTTP_CONTENT_LENGTH:=0}
while read -t 0.01 line; do
# If the line is empty, stop reading headers
if [ -z "$line" ]; then break; fi
# Read each HTTP Header
if echo "${line}" | grep -qi "^some-header:"; then
# do something here
elif echo "${line}" | grep -qi "^Content-Length:"; then
HTTP_CONTENT_LENGTH="$(echo "${line}"|cut -d" " -f 2-)"
fi
done
# Next read from standard input into the HTTP_POST_DATA variable
# (This assumes the request is a POST)
while IFS= read -N $HTTP_CONTENT_LENGTH -r -t 0.01 post_buffer; do
echo "Reading in the HTTP Post Data"
HTTP_POST_DATA="${HTTP_POST_DATA}${post_buffer}"
if [ ${#HTTP_POST_DATA} -ge ${HTTP_CONTENT_LENGTH} ]; then
# Make sure we stop reading, since we have read enough.
break;
fi
done
Зачем использовать IFS =
-r
уже считывает данные без остановки на разделителях IFS
, чтобы убедиться, что bash не изменит наши ожидаемые результаты от необработанного чтения read -r
. Для параметров чтения
:
-t 0.01
определяет тайм-аут чтения в секундах (0,01 сек) -r
флаг читает данные в необработанном виде, игнорируя разделители \ r \ n
-N
читает символы буквально cat
или xargs
или grep .
или что-то еще, что читается со стандартного ввода.