http: error: Request body (from stdin or a file) and request data (key=value) cannot be mixed.
这个错误相当神秘。 我正在编写一个 shell 脚本来与一个 rest API 交互,我正在这样做:
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
我根本没有重定向 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-headers 混合。 但是,我也无法使其正常工作(通过STDIN推送表单数据和作为参数的标题......或通过STDIN作为标题和表单数据的某种组合,或其他)。
我明白了,问题是在循环上下文中 HTTPie 继承了它的STDIN
(被重定向)。
您应该可以通过将 HTTPie 的STDIN
更改回终端输入( < /dev/tty
)来解决它:
cat file | while read line; do
http POST example.org a="$line" < /dev/tty
done
哇。 这样可行。 我不知道 shell 循环的内部语句继承了周围循环的标准输入。
谢谢你的帮助......我不确定我是否会自己找到它。
(现在我很好奇为什么(我假设所有 SH 派生的外壳)做出了这样的设计选择......)
我认为应该有一个选项来禁用STDIN
的读取,它可以在任何地方工作,所以我保持打开状态并将其标记为一个功能。
这非常令人困惑,并且不利于 httpie 能够在任何地方工作。 在 bash 循环中使用这样的命令是一个非常常见的应用程序。 当给定键/值并接收标准输入时,Httpie 不应该抱怨:而是让键/值占主导地位。
当给定键/值并接收标准输入时,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
可用于明确告诉 HTTPie 请求数据(key=value)应该优先于请求正文(来自标准输入)。
http --ignore-stdin http://… lorem=ipsum dolor=sit
参照。 https://httpie.org/docs#redirected -input
在 for 循环中使用http
时遇到此问题。 它在本地运行良好,但在 gitlab 中失败了。 --ignore-stdin
解决了它。
我尝试将 stdin 重定向到 null </dev/null
,但它使 httpie 表现得很奇怪。 为什么? 我的意思是,不应该有一种方法可以让命令忽略 shell 本身的标准输入吗?
@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
?
@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
可用于明确告诉 HTTPie 请求数据(key=value)应该优先于请求正文(来自标准输入)。参照。 https://httpie.org/docs#redirected -input