Я пытаюсь написать простой обработчик для веб-перехватчика с использованием 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
параметр читать остальные? Я до сих пор не очень понимаю, что происходит, поэтому любая информация будет очень полезна.
буквально cat
, или xargs
, или grep .
или что-нибудь еще, что читается из stdin.
Чтобы прочитать стандартные почтовые данные для 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
flag уже считывает данные, не останавливаясь на разделителяхIFS
чтобы убедиться, что bash не изменяет наши ожидаемые результаты от необработанного чтения read -r
.Для read
параметры:
-t 0.01
флаг определяет таймаут чтения в секундах (0,01 сек)-r
flag читает данные в необработанном виде, игнорируя разделители \r\n
-N <num>
flag читает символы <num>.Хорошо, я так и не понял, как читать, пока есть ввод, но я заметил, что в заголовке есть длина. Итак, я анализирую длину, а затем читаю это количество символов:
#!/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.