Httpie: Ajouter une option pour ignorer les données stdin

Créé le 23 juil. 2013  ·  15Commentaires  ·  Source: httpie/httpie

http: error: Request body (from stdin or a file) and request data (key=value) cannot be mixed.

Cette erreur est plutôt cryptique. J'écris un script shell pour interagir avec une API de repos, et je fais ceci :

http --output subnet --pretty format --form post "${URLHOST}subnets" "cidr=${cidr}" "name=${name}" "description=${name}" "availabilityZoneId=${az}" "networkId=${VPCid}" "$ACCESSKEY" "$SECRETKEY" "$ACCOUNTID" "_providerId=aws" "_regionId=${REGION}"

Ce qui produit (lorsqu'il est précédé de 'echo' une commande qui fonctionne parfaitement bien. Cependant, cette version donne l'erreur dans le sujet.

Suis-je stupide ou est-ce autre chose ?

FYI: Le résultat de ce qui précède est le suivant (légèrement désinfecté)

http --output subnet --pretty format --form post https://test.grid.domain.com/subnets cidr=10.124.33.128/25 name=Load_balancers description=Load_balancers availabilityZoneId=us-east-1c networkId=vpc-31433e7e x-gridauth-accesskey:DOYOUNEEDTOKNOW x-gridauth-secretaccesskey:WHATISWITHALLTHEQUESTIONS x-gridauth-accountid:11223344556677 _providerId=aws _regionId=us-east-1
feature planned

Commentaire le plus utile

Pour référence future, il existe maintenant un argument CLI --ignore-stdin qui peut être utilisé pour indiquer explicitement à HTTPie que les données de la requête (clé=valeur) doivent être préférées au corps de la requête (depuis stdin).

http --ignore-stdin http://… lorem=ipsum dolor=sit

Cf. https://httpie.org/docs#redirected -input

Tous les 15 commentaires

Cette erreur se produit lorsque le STDIN de HTTPie est redirigé et que des données sont également spécifiées dans les arguments en même temps :

$ echo 'data' | http POST example.org more=data   # This is invalid

Je ne redirige pas du tout STDIN. Voici un peu plus de contexte dans le script :

cat keyfile  | while read name az route cidr subnetid rest ; do
    http --output subnet --pretty format --form post \
    "${URLHOST}subnets" \
    "cidr=${cidr}" \
    "name=${name}" \
    "description=${name}"\
    "availabilityZoneId=${az}" \
    "networkId=${VPCid}"\
    "$ACCESSKEY" \
    "$SECRETKEY"\
    "$ACCOUNTID" \
    "_providerId=aws" "_regionId=${REGION}"

(puis j'analyse le fichier 'sous-réseau' et continue à faire d'autres choses)

Ce que je pourrais faire, c'est mélanger des champs de formulaire avec des en-têtes http. Cependant, je ne pouvais pas non plus faire fonctionner cela correctement (une combinaison de pousser les données de formulaire via STDIN, et les en-têtes en tant que paramètres... ou en tant qu'en-têtes et données de formulaire via STDIN, ou autre).

Je vois, le problème est que dans le contexte de la boucle, HTTPie hérite de son STDIN (qui est redirigé).

Vous devriez pouvoir contourner le problème en remplaçant le STDIN de HTTPie par l'entrée du terminal ( < /dev/tty ):

cat file | while read line; do 
    http POST example.org  a="$line" < /dev/tty
done

Wow. Ça marche. Je n'avais AUCUNE idée que les instructions internes d'une boucle shell héritent du stdin de la boucle environnante.

Merci pour l'aide... Je ne suis pas sûr que j'aurais trouvé ça tout seul.

(Maintenant, je suis curieux de savoir pourquoi (je suppose que tous les obus dérivés SH) ont fait ce choix de conception...)

Je pense qu'il devrait y avoir une option pour désactiver la lecture de STDIN qui fonctionnerait partout, donc je garde cela ouvert et je le marque comme une fonctionnalité.

Ceci est très déroutant et va à l'encontre de la capacité de httpie à travailler n'importe où. L'utilisation d'une telle commande dans une boucle bash est une application très courante. Httpie ne devrait pas se plaindre lorsque la clé/valeur est donnée et qu'il reçoit stdin : à la place, il laisse la clé/valeur dominer.

Httpie ne devrait pas se plaindre lorsque la clé/valeur est donnée et qu'il reçoit stdin : à la place, il laisse la clé/valeur dominer.

C'est peut-être intuitif pour vous, mais pour beaucoup d'autres, l'exact opposé est beaucoup plus intuitif. Parce que l'outillage ne doit pas essayer de deviner, il est de loin préférable de générer une erreur et de vous fournir une trappe de sortie si vous pensez que vous savez mieux, ce que cela fait.

J'ai rencontré ce problème lors de l'utilisation de httpie à l'intérieur d'une fonction passée à GNU parallel :

function call_api {
    local FOO=`http --json --auth $TOKEN: post $HOST/api/foo name="Ţẽṧẗ" < /dev/tty | python3 -c "import json,sys;obj=json.load(sys.stdin);print(obj['result']['id']);"`
    […]
    http --download --auth $TOKEN: GET $HOST/api/bla > /dev/tty
}

export -f call_api
export HOST=…
export TOKEN=…
parallel --env HOST --env TOKEN ::: call_api call_api call_api call_api call_api

Grâce au commentaire ci -dessus, l'invocation de la fonction parallèle fonctionne maintenant. Laisser ce commentaire ici pour référence future 😊

Pour référence future, il existe maintenant un argument CLI --ignore-stdin qui peut être utilisé pour indiquer explicitement à HTTPie que les données de la requête (clé=valeur) doivent être préférées au corps de la requête (depuis stdin).

http --ignore-stdin http://… lorem=ipsum dolor=sit

Cf. https://httpie.org/docs#redirected -input

Rencontré cela lors de l'utilisation http dans une boucle for. Cela a bien fonctionné localement, mais a échoué dans gitlab. --ignore-stdin l'a résolu.

J'ai essayé de rediriger stdin vers null </dev/null , mais cela a rendu httpie bizarre. Pourquoi ça? Je veux dire, ne devrait-il pas y avoir un moyen de faire en sorte qu'une commande ignore stdin à partir du shell lui-même?

@NightMachinary , vous souhaitez utiliser l'option --ignore-stdin . C'est ainsi que vous dites à HTTPie de ne pas lire STDIN .

$ echo 'this STDIN data is ignored' | http  --ignore-stdin POST httpbin.org/post hello=world

@jakubroztocil Je sais que, je dis si http n'avait pas --ignore-stdin , comment pourrions-nous éliminer stdin allant à http du shell lui-même ?

@NightMachinary vous ne pouvez pas éliminer STDIN (et les autres flux standard), mais vous pouvez le fermer :

$ echo ignored data | http httpbin.org/anything 0<&-

https://superuser.com/questions/813472/how-do-i-close-stdin-in-a-shell-script

@NightMachinary et rediriger /dev/null est un peu différent :

$ http httpbin.org/anything < /dev/null

Cela invoque toujours HTTPie avec un STDIN ouvert et redirigé, donc HTTPie le lira et se retrouvera avec une chaîne vide, qu'il utilisera ensuite avec plaisir comme données du corps de la requête (par défaut, POST ), sauf si vous lui dites de ne pas le faire avec --ignore-stdin .

Donc, c'est fondamentalement équivalent à ceci:

$ echo -n | http httpbin.org/anything 
Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

eliangcs picture eliangcs  ·  5Commentaires

a-x- picture a-x-  ·  7Commentaires

ghost picture ghost  ·  5Commentaires

rashthedude picture rashthedude  ·  3Commentaires

mattotodd picture mattotodd  ·  3Commentaires