Curl返回http状态代码和响应

时间:2016-08-11 21:46:37

标签: shell curl

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

获取http标头
curl -I http://localhost

要获得回复,我使用命令

curl http://localhost

只要使用-I标志,我只获得标题,响应不再存在。有没有办法在一个命令中同时获取http响应和headers / http状态代码?

18 个答案:

答案 0 :(得分:53)

我能够通过查看指定使用的curl doc来获得解决方案 - 输出将输出输出到stdout。

curl -o - http://localhost

要仅使用http返回码获取响应,我就可以

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

答案 1 :(得分:20)

我使用此命令打印状态代码而没有任何其他输出。此外,它只会执行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 ]'

答案 2 :(得分:16)

详细模式会告诉你一切

curl -v http://localhost

答案 3 :(得分:11)

我用过这个:

    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

答案 4 :(得分:4)

-i选项是您想要的选项:

curl -i http://localhost
  

-i,--include在输出(H / F)中包括协议标头

或者,您可以使用详细选项:

curl -v http://localhost
  

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

答案 5 :(得分:4)

单行,只是为了获取状态代码:

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

答案 6 :(得分:3)

我实现这一目标的方法

要同时获得(标题和正文),我通常会执行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)转储到标准输出(-)(在man curl中查找--dump-header)。

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

我经常使用jq来格式化json数据(例如,从其他REST 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请求(在man curl中查找--head。是的:对于大多数HTTP服务器,这将产生相同的结果但是,我知道很多业务应用程序根本没有实现HEAD请求;-P

答案 7 :(得分:3)

获取响应代码和响应:

$ 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:删除任何前导空格

答案 8 :(得分:3)

这里有一些不错的答案,但就像我发现自己在脚本上下文中想要的 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 .

答案 9 :(得分:2)

我发现了这个问题,因为我想同时提供响应和内容,以便为用户添加一些错误处理。

您可以打印HTTP代码以将其输出并将其内容写入另一个文件。

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

答案 10 :(得分:2)

对于编程用途,我使用以下内容:

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,
  ...
}

答案 11 :(得分:2)

一个清晰的使用管道读取

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

欢迎使用我的 dotfile 脚本 here

说明

  • --silent:使用管道时不显示进度条
  • head -n 1:只显示第一行
  • -F' ':使用分隔符空格按列分隔文本
  • '{print $2}':显示第二列

答案 12 :(得分:1)

在行末添加“ 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

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

答案 13 :(得分:1)

根据我的经验,我们通常以这种方式使用curl

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

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

通过这种方式,我们可以在卷曲失败时传递卷曲,并且还显示状态代码。

答案 14 :(得分:0)

这是一种检索主体“与”状态代码并将其格式化为适当的json或任何适合您的格式的方法。有人可能会争辩说这是对write format选项的错误使用,但是当我在脚本中同时需要正文和状态代码来检查状态代码并中继来自服务器的响应时,这对我有用。

curl -X GET \
 -w "%{stderr}{\"status\": \"%{http_code}\", \"body\":%{stdout}}"  -s -o - \
     "https://jsonplaceholder.typicode.com/posts?userId=1" 2>&1 | jq

运行上面的代码,您应该以以下格式返回json:

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

使用-w写格式选项,因为先打印stderr,所以可以使用var http_code格式化输出,并将响应的正文放置在一个值(正文)中,然后使用var stdout进行后续封装。然后将您的stderr输出重定向到stdout,您将能够将http_code和响应正文组合成一个整洁的输出

答案 15 :(得分:0)

哇,这么多答案,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”参数,因为这是在脚本中添加的内容

答案 16 :(得分:0)

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

注意 - 使用 tee 将输出附加到文件和控制台中,这解决了我的目的。

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

希望这对一些人有所帮助。

答案 17 :(得分:-2)

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