Httpie: Adicionar opção para ignorar dados stdin

Criado em 23 jul. 2013  ·  15Comentários  ·  Fonte: httpie/httpie

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

Este erro é bastante enigmático. Estou escrevendo um script de shell para interagir com uma API de descanso e estou fazendo isso:

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}"

Que produz (quando precedido de 'echo' um comando que funciona perfeitamente bem. Porém, esta versão dá o erro no assunto.

Estou sendo estúpido, ou isso é outra coisa?

FYI: O resultado do acima é o seguinte (ligeiramente higienizado)

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

Comentários muito úteis

Para referência futura, agora há um argumento CLI --ignore-stdin que pode ser usado para informar explicitamente ao HTTPie que os dados da solicitação (chave=valor) devem ser preferidos ao corpo da solicitação (de stdin).

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

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

Todos 15 comentários

Este erro ocorre quando o STDIN do HTTPie é redirecionado e os dados também são especificados nos argumentos ao mesmo tempo:

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

Não estou redirecionando STDIN. Aqui está um pouco mais de contexto no 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}"

(e então eu analiso o arquivo 'subnet' e faço outras coisas)

O que eu poderia estar fazendo é misturar campos de formulário com cabeçalhos http. No entanto, também não consegui fazer isso funcionar corretamente (alguma combinação de enviar os dados do formulário por meio de STDIN e cabeçalhos como parâmetros ... ou como cabeçalhos e dados de formulário por meio de STDIN ou qualquer outra coisa).

Entendo, o problema é que no contexto de loop HTTPie herda seu STDIN (que é redirecionado).

Você deve ser capaz de contornar isso alterando o STDIN do HTTPie de volta para a entrada do terminal ( < /dev/tty ):

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

Uau. Isso funciona. Eu não tinha ideia de que as instruções internas de um loop de shell herdam o stdin do loop ao redor.

Obrigado pela ajuda... Não tenho certeza se teria encontrado isso sozinho.

(Agora estou curioso por que (suponho que todos os shells derivados de SH) fizeram essa escolha de design ...)

Eu acho que deveria haver uma opção para desabilitar a leitura de STDIN que funcionaria em qualquer lugar, então estou mantendo isso aberto e marcando-o como um recurso.

Isso é muito confuso e vai contra o httpie poder trabalhar em qualquer lugar. Usar esse comando dentro de um loop bash é uma aplicação muito comum. O Httpie não deve reclamar quando a chave/valor é fornecido e recebe stdin: em vez disso, deixa a chave/valor dominar.

O Httpie não deve reclamar quando a chave/valor é fornecido e recebe stdin: em vez disso, deixa a chave/valor dominar.

Isso talvez seja intuitivo para você, mas para muitos outros o exato oposto é muito mais intuitivo. Como as ferramentas não devem tentar adivinhar, é muito melhor gerar um erro e fornecer uma escotilha de escape se você achar que sabe melhor, o que acontece.

Eu me deparei com esse problema ao usar httpie dentro de uma função passada para o GNU paralelo :

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

Graças ao comentário acima , a invocação da função paralela funciona agora. Deixando este comentário aqui para referência futura 😊

Para referência futura, agora há um argumento CLI --ignore-stdin que pode ser usado para informar explicitamente ao HTTPie que os dados da solicitação (chave=valor) devem ser preferidos ao corpo da solicitação (de stdin).

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

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

Encontrei isso ao usar http em um loop for. Funcionou bem localmente, mas falhou no gitlab. --ignore-stdin resolveu.

Eu tentei redirecionar stdin para null </dev/null , mas fez httpie se comportar de forma estranha. Por que isso? Quero dizer, não deveria haver uma maneira de fazer um comando ignorar stdin do próprio shell?

@NightMachinary você deseja usar a opção --ignore-stdin . É assim que você diz ao HTTPie para não ler STDIN .

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

@jakubroztocil Eu sei disso, estou dizendo que se http não tivesse --ignore-stdin , como poderíamos eliminar stdin indo para http do próprio shell?

@NightMachinary você não pode eliminar STDIN (e os outros fluxos padrão), mas pode fechá-lo:

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

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

@NightMachinary e redirecionar /dev/null é um pouco diferente:

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

Isso ainda invoca o HTTPie com um STDIN aberto e redirecionado, então o HTTPie o lerá e terminará com uma string vazia, que ele usará com prazer como os dados do corpo da solicitação (o padrão é POST ), a menos que você diga para não com --ignore-stdin .

Então é basicamente equivalente a isso:

$ echo -n | http httpbin.org/anything 
Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

mattotodd picture mattotodd  ·  3Comentários

loretoparisi picture loretoparisi  ·  6Comentários

Govinda-Fichtner picture Govinda-Fichtner  ·  6Comentários

pyvotal-cguers picture pyvotal-cguers  ·  5Comentários

maciej picture maciej  ·  4Comentários