Curl返回http状态代码和响应

我使用curl来获取http报头以查找http状态代码并返回响应。我使用命令获取http头信息

curl -I http://localhost

为了得到响应,我使用命令

curl http://localhost

一旦使用了-I标志,我就只得到了头信息,响应就不再存在了。是否有一种方法可以同时获得http响应和头/http状态码在一个命令?

611836 次浏览

我可以通过查看curl文档来得到一个解决方案,该文档指定使用-作为输出来获得输出到stdout。

curl -o - -I http://localhost

要用http返回代码获得响应,我可以这样做

curl -o /dev/null -s -w "%{http_code}\n" http://localhost

我用过这个:

    request_cmd="$(curl -i -o - --silent -X GET --header 'Accept: application/json' --header 'Authorization: _your_auth_code==' 'https://example.com')"

获取HTTP状态

    http_status=$(echo "$request_cmd" | grep HTTP |  awk '{print $2}')
echo $http_status

为了获得响应体,我使用了这个

    output_response=$(echo "$request_cmd" | grep body)
echo $output_response

我使用这个命令打印状态代码,而不输出任何其他结果。此外,它将只执行HEAD请求并遵循重定向(分别为-I-L)。

curl -o -I -L -s -w "%{http_code}" http://localhost

这使得检查运行状况脚本中的状态代码非常容易:

sh -c '[ $(curl -o -I -L -s -w "%{http_code}" http://localhost) -eq 200 ]'

详细模式会告诉你一切

curl -v http://localhost

这个命令

 curl http://localhost -w ", %{http_code}"

将得到以逗号分隔的正文和状态;你可以把它们分开取出来。

您可以随心所欲地更改分隔符。

-i选项是你想要的:

curl -i http://localhost

在输出中包含协议头(H/F)

或者你可以使用verbose选项:

curl -v http://localhost

-v,——verbose使操作更健谈

对于编程使用,我使用以下代码:

curlwithcode() {
code=0
# Run curl in a separate command, capturing output of -w "%{http_code}" into statuscode
# and sending the content to a file with -o >(cat >/tmp/curl_body)
statuscode=$(curl -w "%{http_code}" \
-o >(cat >/tmp/curl_body) \
"$@"
) || code="$?"


body="$(cat /tmp/curl_body)"
echo "statuscode : $statuscode"
echo "exitcode : $code"
echo "body : $body"
}


curlwithcode https://api.github.com/users/tj

显示如下信息:

statuscode : 200
exitcode : 0
body : {
"login": "tj",
"id": 25254,
...
}

我发现这个问题是因为我想要独立访问响应和内容,以便为用户添加一些错误处理。

Curl允许您自定义输出。您可以打印HTTP状态代码以std输出并将内容写入另一个文件

curl -s -o response.txt -w "%{http_code}" http://example.com

这允许您检查返回代码,然后决定是否值得打印响应,处理,日志记录等。

http_response=$(curl -s -o response.txt -w "%{http_code}" http://example.com)
if [ $http_response != "200" ]; then
# handle error
else
echo "Server returned:"
cat response.txt
fi

%{http_code}是一个由curl代替的变量。你可以做更多的事情,或者发送代码到stderr,等等。参见curl手册和--write-out选项。

- w,写出

在完成后的stdout上使curl显示信息 转移。格式为字符串,可以包含plain 混合了任意数量变量的文本。格式可以是 指定为字面的“字符串”,或者可以读取curl 格式从文件"@filename"然后告诉旋度 要从stdin读取格式,请输入"@-"

输出格式中的变量将为 由curl认为合适的值或文本替换,如 下面描述。所有变量都指定为 %{variable_name}和输出一个正常的%你只需要写 它们是%%。您可以使用\n, a输出换行符 回车带\r,制表符带\t,

输出将被写入标准输出,但是这个 可以使用%{stderr}切换到标准错误。

https://man7.org/linux/man-pages/man1/curl.1.html

这是一种找回身体的方法"AND"状态码,并将其格式化为合适的json或任何适合你的格式。有些人可能会认为这是写格式选项的不正确使用,但这对我来说是有效的,当我需要在我的脚本中的主体和状态代码来检查状态代码并从服务器中继回响应。

curl -X GET -w "%{stderr}{\"status\": \"%{http_code}\", \"body\":\"%{stdout}\"}"  -s -o - “https://github.com” 2>&1

运行上面的代码,你应该得到一个json格式:

{
"status" : <status code>,
"body" : <body of response>
}

使用-w write format选项,因为stderr是先打印的,你可以用var http_code格式化你的输出,并将响应的主体放在一个值(body)中,然后使用var stdout跟随封闭。然后将stderr输出重定向到stdout,您将能够将http_code和响应体结合到一个整洁的输出中

while : ; do curl -sL -w "%{http_code} %{url_effective}\\n" http://host -o /dev/null; done

我实现这一目标的方法:

要同时获取(头文件和正文),我通常执行curl -D- <url>,如下所示:

$ curl -D- http://localhost:1234/foo
HTTP/1.1 200 OK
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/json
Date: Wed, 29 Jul 2020 20:59:21 GMT


{"data":["out.csv"]}

这将把头文件(-D)转储到标准输出(-)(在人卷发中查找--dump-header)。

恕我直言,在这种情况下也很方便:

我经常使用金桥来获得json数据(例如从一些其他api)格式化。但由于jq不期望HTTP标头,诀窍是使用-D/dev/stderr将标头打印到stderr。注意,这次我们还使用-sS(——silent,——show-errors)来抑制进度表(因为我们写入管道)。

$ curl -sSD/dev/stderr http://localhost:1231/foo | jq .
HTTP/1.1 200 OK
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/json
Date: Wed, 29 Jul 2020 21:08:22 GMT


{
"data": [
"out.csv"
]
}

我想这也可以很方便,如果你想打印头部(快速检查)控制台,但重定向主体到一个文件(例如,当它的某种二进制不混乱你的终端):

$ curl -sSD/dev/stderr http://localhost:1231 > /dev/null
HTTP/1.1 200 OK
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/json
Date: Wed, 29 Jul 2020 21:20:02 GMT


注意:这与curl -I <url>不同!因为-I将执行HEAD请求,而不是GET请求(在人卷发中查找--head。是:对于大多数HTTP服务器,这将产生相同的结果。但我知道很多商业应用程序根本不实现HEAD请求;-P

附加一行&;http_code:200"在最后,然后grep为关键字"http_code:"并提取响应代码。

result=$(curl -w "\nhttp_code:%{http_code}" http://localhost)


echo "result: ${result}"   #the curl result with "http_code:" at the end


http_code=$(echo "${result}" | grep 'http_code:' | sed 's/http_code://g')


echo "HTTP_CODE: ${http_code}"  #the http response code

在这种情况下,您仍然可以使用非静默模式/ verbose模式来获取有关请求的更多信息,例如curl响应体。

根据我的经验,我们通常这样使用旋度

curl -f http://localhost:1234/foo || exit 1


curl: (22) The requested URL returned error: 400 Bad Request

这样我们就可以在curl失败时使用管道,并且它还显示状态代码。

这里有一些很好的答案,但就像我发现自己想要的OP一样,在脚本环境中,所有的:

  • 服务器返回的任何响应体,而不管响应状态码:有些服务会发送错误细节,例如当响应是错误时,会以JSON形式发送
  • HTTP响应代码
  • curl退出状态码

这很难用一个curl调用来实现,我正在寻找一个完整的解决方案/示例,因为所需的处理很复杂。

我将其他一些关于多路复用stdout/stderr/return-code的bash方法与这里的一些想法结合起来,得到了以下示例:

{
IFS= read -rd '' out
IFS= read -rd '' http_code
IFS= read -rd '' status
} < <({ out=$(curl -sSL -o /dev/stderr -w "%{http_code}" 'https://httpbin.org/json'); } 2>&1; printf '\0%s' "$out" "$?")

那么结果可以在变量中找到:

echo out $out
echo http_code $http_code
echo status $status

结果:

out { "slideshow": { "author": "Yours Truly", "date": "date of publication", "slides": [ { "title": "Wake up to WonderWidgets!", "type": "all" }, { "items": [ "Why <em>WonderWidgets</em> are great", "Who <em>buys</em> WonderWidgets" ], "title": "Overview", "type": "all" } ], "title": "Sample Slide Show" } }
http_code 200
status 0

脚本通过多路复用输出、HTTP响应代码和用空字符分隔的curl退出状态,然后将它们读入当前shell/脚本。它可以用curl请求进行测试,该请求将返回一个>=400响应代码,但也会产生输出。

注意,如果没有-f标志,当服务器返回一个异常的HTTP响应代码,即>=400时,curl将不会返回非零错误代码,并且使用-f标志,服务器输出错误被抑制,利用这个标志进行错误检测和处理不吸引。

带有IFS处理的通用read的积分将转到这个答案:https://unix.stackexchange.com/a/430182/45479

哇,这么多答案,cURL开发人员肯定把它留给了我们作为家庭练习:)好吧,这是我的想法-一个脚本,使cURL工作,因为它应该是,即:

  • 像cURL那样显示输出。
  • 如果HTTP响应代码不在2XX范围内,则使用非零代码退出

保存为curl-wrapper.sh:


#!/bin/bash


output=$(curl -w "\n%{http_code}" "$@")
res=$?


if [[ "$res" != "0" ]]; then
echo -e "$output"
exit $res
fi


if [[ $output =~ [^0-9]([0-9]+)$ ]]; then
httpCode=${BASH_REMATCH[1]}
body=${output:0:-${#httpCode}}


echo -e "$body"


if (($httpCode < 200 || $httpCode >= 300)); then
# Remove this is you want to have pure output even in
# case of failure:
echo
echo "Failure HTTP response code: ${httpCode}"
exit 1
fi
else
echo -e "$output"
echo
echo "Cannot get the HTTP return code"
exit 1
fi

所以它就像往常一样,但不是curl而是./curl-wrapper.sh:

所以当结果在200-299范围内时:

./curl-wrapper.sh www.google.com
# ...the same output as pure curl would return...
echo $?
# 0

当结果超出200-299范围时:

./curl-wrapper.sh www.google.com/no-such-page
# ...the same output as pure curl would return - plus the line
#    below with the failed HTTP code, this line can be removed if needed:
#
# Failure HTTP response code: 404
echo $?
# 1

只是不要通过&;-w|- write-out&;参数,因为这是脚本中添加的内容

一行代码,只是为了获得状态代码:

curl -s -i https://www.google.com | head -1

将其更改为head -2也会给出时间。


如果你想要一个while-true循环,它会是:

URL="https://www.google.com"


while true; do
echo "------"
curl -s -i $URL | head -2
sleep 2;
done

它会产生以下结果,直到执行cmd+C(或Windows中的ctrl+C)。

------
HTTP/2 200
date: Sun, 07 Feb 2021 20:03:38 GMT
------
HTTP/2 200
date: Sun, 07 Feb 2021 20:03:41 GMT
------
HTTP/2 200
date: Sun, 07 Feb 2021 20:03:43 GMT
------
HTTP/2 200
date: Sun, 07 Feb 2021 20:03:45 GMT
------
HTTP/2 200
date: Sun, 07 Feb 2021 20:03:47 GMT
------
HTTP/2 200
date: Sun, 07 Feb 2021 20:03:49 GMT

要获得响应代码和响应:

$ curl -kv https://www.example.org

要得到响应代码:

$ curl -kv https://www.example.org 2>&1 | grep -i 'HTTP/1.1 ' | awk '{print $3}'| sed -e 's/^[ \t]*//'
  • 2>&1:错误存储在输出中用于解析
  • Grep:从输出中过滤响应代码行
  • Awk:从响应代码行中过滤响应代码
  • Sed:删除前导空白

我使用以下方法在控制台中同时获取return coderesponse body

注- __abc1

Sample CURL call for reference:

curl -s -i -k --location --request POST ''${HOST}':${PORT}/api/14/project/'${PROJECT_NAME}'/jobs/import' \
--header 'Content-Type: application/yaml' \
--header 'X-Rundeck-Auth-Token: '${JOB_IMPORT_TOKEN}'' \
--data "$(cat $yaml_file)" &>/dev/stdout | tee -a $response_file


return_code=$(cat $response_file | head -3 | tail -1 | awk {'print $2'})


if [ "$return_code" != "200" ]; then
echo -e "\Job import api call failed with rc: $return_code, please rerun or change pipeline script."
exit $return_code
else
echo "Job import api call completed successfully with rc: $return_code"
fi

希望这能帮助到一些人。

使用管道读取的清除项

function cg(){
curl -I --silent www.google.com | head -n 1 | awk -F' ' '{print $2}'
}
cg
# 200

欢迎使用我的dotfile脚本在这里

< h2 id = " explanation-evf7 " > < / h2 >解释
  • --silent:使用管道时不显示进度条
  • head -n 1:只显示第一行
  • -F' ':使用分隔符空格按列分隔文本
  • '{print $2}':显示第二列

这对我来说很管用:

curl -Uri 'google.com' | select-object StatusCode