如何使用命令行curl显示请求标头

How to display request headers with command line curl

命令行curl可以使用-D选项显示响应头,但我想看看它发送的是什么请求头。我该怎么做?


curl的-v--verbose选项显示HTTP请求头,以及其他内容。以下是一些示例输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$ curl -v http://google.com/
* About to connect() to google.com port 80 (#0)
*   Trying 66.102.7.104... connected
* Connected to google.com (66.102.7.104) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.16.4 (i386-apple-darwin9.0) libcurl/7.16.4 OpenSSL/0.9.7l zlib/1.2.3
> Host: google.com
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Location: http://www.google.com/
< Content-Type: text/html; charset=UTF-8
< Date: Thu, 15 Jul 2010 06:06:52 GMT
< Expires: Sat, 14 Aug 2010 06:06:52 GMT
< Cache-Control: public, max-age=2592000
< Server: gws
< Content-Length: 219
< X-XSS-Protection: 1; mode=block
<
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
301 Moved</HEAD><BODY>
301 Moved
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>
* Connection #0 to host google.com left intact
* Closing connection #0


1
curl -sD - -o /dev/null http://example.com
  • -s—避免显示进度条
  • -D -—将头转储到文件,但-将其发送到stdout
  • -o /dev/null—忽略响应体

这比-I好,因为它不发送HEAD请求,这会产生不同的结果。

它比-v好,因为你不需要那么多的黑客来消除冗长的信息。


我相信你要传递给curl的命令行开关是-I

示例用法:

1
2
3
4
5
6
$ curl -I http://heatmiser.counterhack.com/zone-5-15614E3A-CEA7-4A28-A85A-D688CC418287  
HTTP/1.1 301 Moved Permanently
Date: Sat, 29 Dec 2012 15:22:05 GMT
Server: Apache
Location: http://heatmiser.counterhack.com/zone-5-15614E3A-CEA7-4A28-A85A-D688CC418287/
Content-Type: text/html; charset=iso-8859-1

此外,如果您遇到响应HTTP状态代码301,您可能还需要传递一个-L参数开关,告诉curl遵循URL重定向,在这种情况下,打印所有页面的标题(包括URL重定向),如下图所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ curl -I -L http://heatmiser.counterhack.com/zone-5-15614E3A-CEA7-4A28-A85A-D688CC418287
HTTP/1.1 301 Moved Permanently
Date: Sat, 29 Dec 2012 15:22:13 GMT
Server: Apache
Location: http://heatmiser.counterhack.com/zone-5-15614E3A-CEA7-4A28-A85A-D688CC418287/
Content-Type: text/html; charset=iso-8859-1

HTTP/1.1 302 Found
Date: Sat, 29 Dec 2012 15:22:13 GMT
Server: Apache
Set-Cookie: UID=b8c37e33defde51cf91e1e03e51657da
Location: noaccess.php
Content-Type: text/html

HTTP/1.1 200 OK
Date: Sat, 29 Dec 2012 15:22:13 GMT
Server: Apache
Content-Type: text/html


verbose选项很方便,但是如果您想查看curl所做的一切(包括传输的HTTP主体,而不仅仅是头),我建议使用以下选项之一:

  • --trace-ascii -标准输出
  • --trace-ascii output_file.txt文件


您可以通过以下命令获得一个很好的头输出:

1
 curl -L -v -s -o /dev/null google.de
  • -L, --location跟踪重定向
  • -v, --verbose多输出,表示方向
  • -s, --silent不显示进度条
  • -o, --output /dev/null不显示接收体

或较短版本:

1
 curl -Lvso /dev/null google.de

结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
* Rebuilt URL to: google.de/
*   Trying 2a00:1450:4008:802::2003...
* Connected to google.de (2a00:1450:4008:802::2003) port 80 (#0)
> GET / HTTP/1.1
> Host: google.de
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Location: http://www.google.de/
< Content-Type: text/html; charset=UTF-8
< Date: Fri, 12 Aug 2016 15:45:36 GMT
< Expires: Sun, 11 Sep 2016 15:45:36 GMT
< Cache-Control: public, max-age=2592000
< Server: gws
< Content-Length: 218
< X-XSS-Protection: 1; mode=block
< X-Frame-Options: SAMEORIGIN
<
* Ignoring the response-body
{ [218 bytes data]
* Connection #0 to host google.de left intact
* Issue another request to this URL: 'http://www.google.de/'
*   Trying 2a00:1450:4008:800::2003...
* Connected to www.google.de (2a00:1450:4008:800::2003) port 80 (#1)
> GET / HTTP/1.1
> Host: www.google.de
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Fri, 12 Aug 2016 15:45:36 GMT
< Expires: -1
< Cache-Control: private, max-age=0
< Content-Type: text/html; charset=ISO-8859-1
< P3P: CP="This is not a P3P policy! See https://www.google.com/support/accounts/answer/151657?hl=en for more info."
< Server: gws
< X-XSS-Protection: 1; mode=block
< X-Frame-Options: SAMEORIGIN
< Set-Cookie: NID=84=Z0WT_INFoDbf_0FIe_uHqzL9mf3DMSQs0mHyTEDAQOGY2sOrQaKVgN2domEw8frXvo4I3x3QVLqCH340HME3t1-6gNu8R-ArecuaneSURXNxSXYMhW2kBIE8Duty-_w7; expires=Sat, 11-Feb-2017 15:45:36 GMT; path=/; domain=.google.de; HttpOnly
< Accept-Ranges: none
< Vary: Accept-Encoding
< Transfer-Encoding: chunked
<
{ [11080 bytes data]
* Connection #1 to host www.google.de left intact

如您所见,curl输出输出和输入头,跳过BodyData,尽管它告诉您Body有多大。

另外,每一行都指示方向,这样便于阅读。我发现追踪一长串的重定向特别有用。


调试Web应用程序时,我必须自己解决这个问题。-v很好,但有点太冗长了,不适合我的口味。这是我提出的(仅限于bash)解决方案:

1
curl -v http://example.com/ 2> >(sed '/^*/d')

这是因为来自-v的输出被发送到stderr,而不是stdout。通过将其重定向到子shell,我们可以删除以*开头的行。由于实际输出不通过子shell,因此不会受到影响。使用子shell有点笨手笨脚,但这是将stderr重定向到另一个命令的最简单方法。(正如我所指出的,我只是将它用于测试,所以它对我来说很好。)


curl的-v选项在错误输出中过于冗长,错误输出包含前导的*(状态行)或>(请求头字段)或<(响应头字段)。仅获取请求头字段:

1
curl -v -sS www.stackoverflow.com 2>&1 >/dev/null | grep '>' | cut -c1-2 --complement

仅获取请求头字段:

1
curl -v -sS www.stackoverflow.com 2>&1 >/dev/null | grep '<' | cut -c1-2 --complement

或者用-d选项将其转储到/tmp/test.txt文件中

1
curl -D /tmp/test.txt -sS www.stackoverflow.com > /dev/null

为了过滤-v输出,您应该将错误输出指向终端,std输出指向/dev/null,-s选项是禁止进度计量。


像下面这样的命令将显示三个部分:请求头、响应头和数据(由CRLF分隔)。它避免了由curl添加的技术信息和语法噪声。

1
curl -vs www.stackoverflow.com 2>&1 | sed '/^* /d; /bytes data]$/d; s/> //; s/< //'

命令将生成以下输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
GET / HTTP/1.1
Host: www.stackoverflow.com
User-Agent: curl/7.54.0
Accept: */*

HTTP/1.1 301 Moved Permanently
Content-Type: text/html; charset=UTF-8
Location: https://stackoverflow.com/
Content-Length: 149
Accept-Ranges: bytes
Date: Wed, 16 Jan 2019 20:28:56 GMT
Via: 1.1 varnish
Connection: keep-alive
X-Served-By: cache-bma1622-BMA
X-Cache: MISS
X-Cache-Hits: 0
X-Timer: S1547670537.588756,VS0,VE105
Vary: Fastly-SSL
X-DNS-Prefetch-Control: off
Set-Cookie: prov=e4b211f7-ae13-dad3-9720-167742a5dff8; domain=.stackoverflow.com; expires=Fri, 01-Jan-2055 00:00:00 GMT; path=/; HttpOnly

<head>Document Moved</head>
<body>Object MovedThis document may be found here</body>

描述:

  • -vs—添加头文件(-v),但删除进度条(-s)
  • 2>&1—将stdout和stderr合并为单个stdout
  • sed—使用下面的命令编辑curl生成的响应
  • /^* /d-删除以"*"开头的行(技术信息)
  • /bytes data]$/d-删除以"字节数据"结尾的行(技术信息)
  • s/> //-删除">"前缀
  • s/< //-删除'<'前缀

如果你想要更多的选择,你可以尝试安装一个现代的命令行HTTP客户端,比如httpie,它适用于大多数带有包管理器的操作系统,比如brew、apt-get、pip、yum等。

对于OSX

1
brew install httpie

然后,您可以在命令行上使用它和各种选项

1
http GET https://www.google.com

enter image description here


在PHP中设置卷曲选项

curlinfo_header_out=>真,

1
CURLOPT_HEADER => 1,

可能将头结果转储到mysql中。以便于日志记录。

如果使用浏览器比F12/Firebug提供的更详细,也可以使用Wireshark。