卷曲以返回 http 状态代码以及响应

Posted

技术标签:

【中文标题】卷曲以返回 http 状态代码以及响应【英文标题】:Curl to return http status code along with the response 【发布时间】:2016-12-18 19:10:00 【问题描述】:

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

curl -I http://localhost

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

curl http://localhost

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

【问题讨论】:

这是一个非常有用的sn-p gist.github.com/maxcnunes/9f77afdc32df354883df 【参考方案1】:

我能够通过查看 curl 文档来获得解决方案,该文档指定使用 - 作为输出以将输出输出到标准输出。

curl -o - http://localhost

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

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

【讨论】:

或者你会使用-i。或者-v,如果您也想了解更多信息。 感谢@DanielStenberg。接受的答案对我不起作用,只需使用 -i 确实有效。 您的第二个命令丢失了 -I @randominstanceOfLivingThing,除非这是故意的空白选项?没有它对我不起作用 -o -I 最终在 CWD 中创建了一个名为“-I”的文件。有没有其他人看到这个?解决方案是-o/dev/null -I 删除了 -I。我现在注意到并纠正了。你不需要 -I。【参考方案2】:

详细模式会告诉你一切

curl -v http://localhost

【讨论】:

我认为这是正确的答案。 如果响应也有有效载荷(在我的情况下发送的状态码未打印出来是 503),则对我不起作用【参考方案3】:

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

Curl 允许您自定义输出。 您可以将 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

%http_code 是一个被 curl 替换的变量。您可以做更多事情,或将代码发送到 stderr 等。请参阅 curl 手册和 --write-out 选项。

-w, --write-out

完成后让 curl 在标准输出上显示信息 转移。格式是一个可能包含纯文本的字符串 文本与任意数量的变量混合。格式可以是 指定为文字“字符串”,或者您可以让 curl 读取 来自带有“@filename”的文件的格式并告诉 curl 要从标准输入读取格式,请写“@-”。

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

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

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

【讨论】:

什么是http_code?没看懂,请多多解释 上面澄清了,它指的是HTTP状态码-developer.mozilla.org/en-US/docs/Web/HTTP/Status 根据这个答案和接受的创建一个 bash 脚本,重试 curl 调用:***.com/a/70522459/6344916。谢谢!【参考方案4】:

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

【讨论】:

这个问题在一年前就已经回答过了。你的回答带来了什么新价值?也请给你的答案写一些解释。 @MaciejJureczko - 值很简单。出于脚本目的,这个答案是所有其他答案中最好的,因为它提供了一个状态代码,而不是许多行垃圾以及所述状态代码。 但是 OP 特别声明他们想要 both 状态代码和响应正文。他们知道如何获取响应代码(在问题中说明) 每当我使用这个curl -o -I -L -s -w "%http_code" http://localhost 时,都会创建一个名为-I 的文件,为了解决这个问题,我为-o 暗示的文件输出添加了一个位置,即/dev/null:@ 987654329@ HEAD 并不总是产生与请求相同的输出,这取决于服务器如何响应。所以这不是一个真正的答案。【参考方案5】:

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

curl -i http://localhost

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

您也可以使用详细选项:

curl -v http://localhost

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

【讨论】:

-i 存在一个陷阱,因为您有时会在输出中收到两组 HTTP 响应代码,例如带有 HTTP/1.1 100 Continue 标头,然后是 HTTP/1.1 200 OK 标头。你可以禁用这个期望机制见gms.tf/when-curl-sends-100-continue.html【参考方案6】:

我用过这个:

    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

【讨论】:

【参考方案7】:

这个命令

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

会得到逗号分隔的正文和状态;您可以拆分它们以将它们取出。

您可以随意更改分隔符。

【讨论】:

好提示!是否可以在输出前添加状态码? 我发现这个答案也很有帮助。并回答@Psychozoic 的问题......我找不到办法,但添加新的行分隔符有助于突出显示响应正文中的响应代码,并且我的命令提示符出现在与响应代码相同的行上。试试这个:curl http://localhost -w "\nResponse Code: %http_code\n"" @benhorgen 下一个答案对此有帮助,请检查!【参考方案8】:

这是一种检索正文“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 写入格式选项,由于首先打印 stderr,您可以使用 var http_code 格式化输出,并将响应的主体放在一个值(主体)中,然后使用 var stdout 跟进封闭。然后将您的标准错误输出重定向到标准输出,您将能够将 http_code 和响应正文组合成一个整洁的输出

【讨论】:

得到以下错误 - curl: unknown --write-out variable: 'stderr'curl: unknown --write-out variable: 'stdout' curl.haxx.se/docs/manpage.html 手册页显示可用的变量。不知道为什么您的 curl 无法识别 stderr,这是 macbook 上的 curl 即时消息。从这个 Linux curl 文档,computerhope.com/unix/curl.htm,我也不认为 stderr 是一个变量。也许这是操作系统的变体。 我唯一的问题是如果你的正文有引号,例如如果它的 json,正文会使 json 响应高于无效 json 足够公平@theannouncer,我希望开发人员进行相应调整,因为并非所有响应都是标准 json。由于响应的性质,在某些情况下我不得不进行调整。【参考方案9】:

获取响应代码和响应:

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

【讨论】:

【参考方案10】:

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

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】:

我的方法

为了同时获取(标题和正文),我通常执行curl -D- &lt;url&gt;,如下所示:

$ 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 &lt;url&gt; 不同!因为-I 将执行HEAD 请求而不是GET 请求(在man curl 中查找--head。是的:对于大多数HTTP 服务器,这将产生相同的结果。但我知道很多业务应用程序根本不执行HEAD 请求;-P

【讨论】:

【参考方案12】:

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

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 -sSi $URL | head -2 | tr -d '\r' | tr '\n' ' '; echo; 将使其成为单行输出。 那为什么不curl -L -I -s -f -w "%http_code" https://google.com | tail -n1 200% curl -L -I -s -f -w "%http_code" https://test.google.com | tail -n1 000% curl -L -I -s -f -w "%http_code" https://google.com/aaa | tail -n1 404% @AndriiTishchenko 我无法运行你提到的命令。 抱歉,有 3 个单独的:curl -L -I -s -f -w "%http_code" https://google.com | tail -n1【参考方案13】:

一个清晰的使用管道读取

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

cg
# 200

欢迎使用我的点文件脚本here

解释

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

【讨论】:

【参考方案14】:

这里有一些很好的答案,但就像我发现自己想要的 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 标志,curl 在服务器返回异常HTTP 响应码即>=400 时不会返回非零错误码,而使用-f 标志,服务器输出将被抑制发生错误时,使用此标志进行错误检测和处理没有吸引力。

使用 IFS 处理的通用 read 的学分转到此答案:https://unix.stackexchange.com/a/430182/45479。

【讨论】:

【参考方案15】:

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

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

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

这样我们可以在 curl 失败时通过管道传递它,并且它还会显示状态码。

【讨论】:

【参考方案16】:

在末尾追加一行“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 响应正文。

【讨论】:

【参考方案17】:

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

【讨论】:

【参考方案18】:

我使用以下方式在控制台中同时获取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

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

【讨论】:

【参考方案19】:

这对我有用:

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

【讨论】:

这个答案与 Powershell 的 Invoke-WebRequest 别名有关,而不是 curl。【参考方案20】:
while : ; do curl -sL -w "%http_code %url_effective\\n" http://host -o /dev/null; done

【讨论】:

你为什么要把它放在一个while循环中?请扩展并解释您的答案。

以上是关于卷曲以返回 http 状态代码以及响应的主要内容,如果未能解决你的问题,请参考以下文章

cURL 可以检测到 307 响应吗?

HTTP 状态码

各类 HTTP 返回状态代码详解

如何获取返回 Http 状态代码 406 或 400 的 API 的响应 JSON

各类 HTTP 返回状态代码详解

各类 HTTP 返回状态代码详解