1 votes

Xinetd lire les données post

Je suis en train d'essayer d'écrire un simple gestionnaire pour un webhook en utilisant xinetd et bash. J'ai le cas trivial fonctionnant avec cette configuration pour xinetd:

service github-hooks
{
    port            = 61000
    socket_type     = stream
    protocol        = tcp
    wait            = no
    user            = ubuntu
    server          = /home/ubuntu/github-hooks.sh
}

et ce script bash:

#!/bin/bash
echo -e "HTTP/1.1 200 OK"

Maintenant, je veux lire les données post qui sont envoyées dans le webhook afin de pouvoir faire quelque chose de plus intéressant que de renvoyer toujours 200.

Comment puis-je lire les données post depuis mon script bash?

J'ai essayé:

while read line; do
    echo "$line" >> /home/ubuntu/test
done < /dev/stdin

mais ça ne fonctionne pas pour moi.

Édition

Grâce à la suggestion ci-dessous, j'ai arrêté xinetd et utilisé nc pour voir quelles données brutes arrivaient sur le fil:

$nc -l 61000

et j'ai obtenu ceci:

POST / HTTP/1.1
Host: :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": 

Donc, les données sont envoyées. Maintenant, sachant qu'il y a exactement 11 lignes envoyées, je lis exactement 11 lignes:

for i in {0..10}
do
    read line
    echo "$line" >> /home/ubuntu/test
done

Et, j'obtiens la même sortie (grand succès :)

POST / HTTP/1.1
Host: :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": 

Peut-être devrais-je juste lire 9 lignes puis utiliser le paramètre Content-Length pour lire le reste? Je ne comprends toujours pas vraiment ce qui se passe donc toute information serait très utile.

0voto

CyberMew Points 156

D'accord, je n'ai jamais réussi à comprendre comment lire tant qu'il y a une entrée, mais j'ai remarqué qu'il y a une longueur dans l'en-tête. Ainsi, je sépare la longueur puis je lis ce nombre de caractères :

#!/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"

Et, maintenant j'ai les données post que github envoie.

0voto

Russell E Glaue Points 861

Pour lire les données de publication standard pour une requête http xinetd, un programme lit simplement l'entrée standard.

J'ai écrit un script bash qui lit et analyse les en-têtes http tels qu'ils sont transmis via l'entrée standard. Utile lorsqu'il est appelé depuis xinetd. J'ai créé ceci comme point de départ pour quelqu'un qui veut créer un service xinetd qui peut reconnaître des appels HTTP de type REST. https://github.com/rglaue/xinetd_bash_http_service

Essentiellement, lire l'entrée HTTP (en-têtes et données POST) dans un service xinetd ressemble à ceci :

# Lire les entêtes HTTP, ligne par ligne
# Nous recherchons l'en-tête HTTP Content-Length
: ${HTTP_CONTENT_LENGTH:=0}
while read -t 0.01 line; do
    # Si la ligne est vide, arrêtez de lire les en-têtes
    if [ -z "$line" ]; then break; fi
    # Lire chaque en-tête HTTP
    if echo "${line}" | grep -qi "^some-header:"; then
      # faire quelque chose ici
    elif echo "${line}" | grep -qi "^Content-Length:"; then
      HTTP_CONTENT_LENGTH="$(echo "${line}"|cut -d" " -f 2-)"
    fi
done
# Ensuite, lire depuis l'entrée standard dans la variable HTTP_POST_DATA
# (Cela suppose que la demande est un POST)
while IFS= read -N $HTTP_CONTENT_LENGTH -r -t 0.01 post_buffer; do
    echo "Lecture des données de publication HTTP"
    HTTP_POST_DATA="${HTTP_POST_DATA}${post_buffer}"
    if [ ${#HTTP_POST_DATA} -ge ${HTTP_CONTENT_LENGTH} ]; then
      # Assurez-vous que nous arrêtons de lire, puisque nous avons lu suffisamment.
      break;
    fi
done

Pourquoi utiliser IFS=

  • Le drapeau -r lit déjà les données sans s'arrêter aux délimiteurs
  • IFS est le séparateur de champ interne utilisé par bash pour déterminer comment les mots sont séparés, et comment les lignes sont séparées.
  • Nous vidons IFS pour nous assurer que bash ne change pas nos résultats attendus de la lecture brute read -r.

Pour les paramètres de read :

  • Le drapeau -t 0.01 définit le délai d'attente de lecture en secondes (0.01 sec)
  • Le drapeau -r lit les données de manière brute, ce qui ignore les délimiteurs \r\n
  • Le drapeau -N lit caractères.

0voto

christianlc Points 121

Littéralement cat, ou xargs, ou grep . ou tout autre chose qui lit à partir de stdin.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X