http: error: Request body (from stdin or a file) and request data (key=value) cannot be mixed.
このエラーはかなり不可解です。 私はRESTAPIと対話するためのシェルスクリプトを書いています、そして私はこれをしています:
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}"
これにより、(「echo」が前に付いている場合、完全に機能するコマンドが生成されます。ただし、このバージョンでは、件名にエラーが発生します。
私は愚かですか、それともこれは他の何かですか?
参考:上記の結果は以下のとおりです(若干消毒)
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
このエラーは、HTTPieのSTDIN
がリダイレクトされ、同時に引数にデータも指定されている場合に発生します。
$ echo 'data' | http POST example.org more=data # This is invalid
STDINをまったくリダイレクトしていません。 スクリプトのコンテキストは次のとおりです。
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}"
(次に、「サブネット」ファイルを解析し、他のことを続けます)
私がやっていることは、フォームフィールドとhttpヘッダーを混在させることです。 ただし、それを正しく機能させることはできませんでした(STDINを介してフォームデータをプッシュし、パラメーターとしてヘッダーをプッシュするか、STDINを介してヘッダーとフォームデータをプッシュするなどの組み合わせ)。
なるほど、問題は、ループコンテキストでHTTPieがSTDIN
(リダイレクトされる)を継承することです。
HTTPieのSTDIN
をターミナル入力( < /dev/tty
)に戻すことで、この問題を回避できるはずです。
cat file | while read line; do
http POST example.org a="$line" < /dev/tty
done
わお。 それはうまくいきます。 シェルループの内部ステートメントが周囲のループのstdinを継承していることを私は知りませんでした。
助けてくれてありがとう...自分でそれを見つけたかどうかはわかりません。
(今、なぜ(すべてのSH派生シェルを想定している)その設計を選択したのか興味があります...)
どこでも機能するSTDIN
の読み取りを無効にするオプションがあるはずだと思うので、これを開いたままにして、機能としてタグ付けします。
これは非常に紛らわしく、httpieがどこでも作業できることに反します。 bashループ内でこのようなコマンドを使用することは、非常に一般的なアプリケーションです。 キー/値が指定され、stdinを受け取った場合、Httpieは文句を言うべきではありません。代わりに、キー/値を支配させます。
キー/値が指定され、stdinを受け取った場合、Httpieは文句を言うべきではありません。代わりに、キー/値を支配させます。
それはおそらくあなたにとって直感的ですが、他の多くの人にとっては正反対の方がはるかに直感的です。 ツールは推測を試みるべきではないので、エラーを発生させて、よく知っていると感じた場合はエスケープハッチを提供する方がはるかに優れています。
GNU parallelに渡された関数内でhttpieを使用しているときに、この問題が発生しました。
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
上記のコメントのおかげで、並列関数の呼び出しが機能するようになりました。 今後の参考のためにこのコメントをここに残してください😊
今後の参考のために、CLI引数--ignore-stdin
があります。これを使用して、リクエストデータ(key = value)がリクエスト本文(stdinから)よりも優先されることをHTTPieに明示的に伝えることができます。
http --ignore-stdin http://… lorem=ipsum dolor=sit
Cf. https://httpie.org/docs#redirected -input
forループでhttp
を使用しているときにこれが発生しました。 ローカルでは正常に機能しましたが、gitlabでは失敗しました。 --ignore-stdin
それを解決しました。
stdinをnull </dev/null
にリダイレクトしようとしましたが、httpieの動作がおかしくなりました。 なんで? つまり、コマンドにシェル自体からのstdinを無視させる方法があるべきではありませんか?
@NightMachinary --ignore-stdin
オプションを使用します。 これが、HTTPieにSTDIN
を読み取らないように指示する方法です。
$ echo 'this STDIN data is ignored' | http --ignore-stdin POST httpbin.org/post hello=world
@jakubroztocil私が知っているのは、 http
に--ignore-stdin
$がなかった場合、シェル自体からhttp
に行くstdinをどのように排除できるでしょうか。
@NightMachinary STDIN
(およびその他の標準ストリーム)を削除することはできませんが、閉じることはできます。
$ echo ignored data | http httpbin.org/anything 0<&-
https://superuser.com/questions/813472/how-do-i-close-stdin-in-a-shell-script
@NightMachinaryとリダイレクト/dev/null
は少し異なります:
$ http httpbin.org/anything < /dev/null
これでも、オープンでリダイレクトされたSTDIN
でHTTPieが呼び出されるため、HTTPieはそれを読み取り、空の文字列になります。これは、リクエストの本文データとして喜んで使用されます(実質的にデフォルトはPOST
)、 --ignore-stdin
を使用しないように指示しない限り。
したがって、基本的にこれと同等です。
$ echo -n | http httpbin.org/anything
最も参考になるコメント
今後の参考のために、CLI引数
--ignore-stdin
があります。これを使用して、リクエストデータ(key = value)がリクエスト本文(stdinから)よりも優先されることをHTTPieに明示的に伝えることができます。Cf. https://httpie.org/docs#redirected -input