Skip to content
On this page

总结

  • curl url: 发起 get 请求

    • -X/--request: 指定请求方法
    • -I/--head: 发送 HEAD 请求,只返回响应头
    • -i/--include: 返回响应头 和 响应体
    • -v/--verbose: 查看详细过程,查看发送、响应以及 TLS handshake 过程。-vvv 多个 v 为更详细
    • -L/--location: 追踪重定向
    • -H: 添加头信息
    • -d: 添加请求体,文件用 @
  • http:

    • [METHOD] url: 发起请求
    • -f/--form: Content-Type: application/x-www-form-urlencoded
    • -F/--follow: 追踪重定向
    • --multipart: Content-Type: multipart/form-data 文件用 @

这里的响应头实际是:响应行 + 响应头

提问

  • [x] 1. curl/httpie 如何发送一个 GET 请求

    curl httpbin.org/get [-X GET] 不要写成小写的 get
    http [GET] httpbin.org/get

  • [x] 2. curl/httpie 如何发送 JSON 数据给服务器端

    curl httpbin.org/post -X POST -H "content-type: application/json" -d '{"age": "18"}'
    http POST httpbin.org/post age=18

  • [x] 3. curl/httpie 如何发送 FORM 数据给服务器端

    curl httpbin.org/post -X POST -d age=18
    http -f POST httpbin.org/post age=18

  • [x] 4. curl/httpie 如何追踪重定向路径

    curl httpbin.org/absolute-redirect/1 -L
    http httpbin.org/absolute-redirect/1 -F

  • [x] 5. curl/httpie 如何仅返回 Response Header

    curl httpbin.org/get -I
    http HEAD httpbin.org/get 如果是只打印响应头 -ph 或者 -h/--head/--headers

1. 前提提要、场景

curl,用于发送请求的命令行工具,一个 HTTP 请求客户端(实际上它也可以做 FTP/SCP/TELNET 协议的事情),可在命令行中发起请求。类似浏览器中的 fetch

SCP: 全称 Secure Copy,指两个主机之间基于 SSH 协议进行安全的远程文件传输。
TELNET: 提供了连接远程主机的能力,与 SSH 类似。应用层协议,基于 TCPSSH 协议在发送数据时会对数据进行加密操作,数据传输更安全,因此 SSH 协议几乎在所有应用领域代替了 Telnet 协议。在一些测试、无需加密的场合(如局域网),Telnet 协议仍常被使用。

在学习及调试 HTTP 的过程中,可结合 curl httpbin 一同使用。httpbin 可用以测试 HTTP 各种方法、状态码、头部、基本认证及摘要认证等

2. curl

2.1 curl url 发起 get 请求

紧跟 URL,发起 get 请求,默认只返回响应体
命令:curl <url>
示例:curl ifconfig.me

sh
# https://ifconfig.me 是一个获取客户端公网 IP 的服务。
$ curl ifconfig.me
118.73.227.215#

2.2 curl -X/--request 指定请求方法

命令:curl <url> -X <method>
示例:curl https://httpbin.org/post -X POST

sh
# -X: 指定请求方法
# -H: 添加请求头。请求头不区分大小写。
$ curl https://httpbin.org/post -X POST -H "a: 3" -H "b: 4"

{
  "args": {},
  "data": "",
  "files": {},
  "form": {},
  "headers": {
    "A": "3",
    "Accept": "*/*",
    "B": "4",
...

2.3 curl -I/--head 发送 HEAD 请求 / 只返回响应头

发送 HEAD 请求,只返回响应头
命令:curl <url> -I
示例:curl https://httpbin.org/get -I

sh
$ curl https://httpbin.org/get -I

HTTP/2 200 
date: Sun, 04 Dec 2022 03:37:07 GMT
content-type: application/json
content-length: 253
server: gunicorn/19.9.0
access-control-allow-origin: *
access-control-allow-credentials: true

2.4 curl -i/--include 返回响应头 和 响应体

返回响应头 和 响应体
命令:curl <url> -i
示例:curl https://httpbin.org/get -i

sh
# 返回响应头 和 响应体    
$ curl https://httpbin.org/get -i

HTTP/2 200 
date: Sun, 04 Dec 2022 05:09:41 GMT
content-type: application/json
content-length: 253
server: gunicorn/19.9.0
access-control-allow-origin: *
access-control-allow-credentials: true

{
  "args": {},
  "headers": {
    "Accept": "*/*",
    "Host": "httpbin.org",
    "User-Agent": "curl/7.64.0",
    "X-Amzn-Trace-Id": "Root=1-638c2b95-157d55a4332670744ae0efd9"
  },
  "origin": "xxx.xx.xx.xx",
  "url": "https://httpbin.org/get"
}

ps:可以看到 HTTP2 响应行 200 后面没有 OK 的描述了。因为常见的字段有一份静态索引表维护 Static Table Definition

2.5 curl -v/--verbose 查看详细过程

查看发送、响应以及 TLS handshake 过程
命令:curl <url> -v 或者更详细 curl <url> -vvv
示例:curl https://shanyue.tech/ -vvv

sh
# -vvv: 查看更详细的过程,如 TLS handshake
$ curl https://shanyue.tech/ -vvv -I
*   Trying 122.228.7.237...
* TCP_NODELAY set
* Connected to shanyue.tech (122.228.7.237) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, [no content] (0):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=shanyue.tech
*  start date: Feb  5 00:00:00 2022 GMT
*  expire date: Feb  6 23:59:59 2023 GMT
*  subjectAltName: host "shanyue.tech" matched cert's "shanyue.tech"  
*  issuer: C=US; O=DigiCert Inc; OU=www.digicert.com; CN=Encryption Everywhere DV TLS CA - G1
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* TLSv1.3 (OUT), TLS app data, [no content] (0):
* TLSv1.3 (OUT), TLS app data, [no content] (0):
* TLSv1.3 (OUT), TLS app data, [no content] (0):
* Using Stream ID: 1 (easy handle 0x561384565690)
* TLSv1.3 (OUT), TLS app data, [no content] (0):
> HEAD / HTTP/2
> Host: shanyue.tech
> User-Agent: curl/7.61.1
> Accept: */*
>
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS app data, [no content] (0):
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
* TLSv1.3 (OUT), TLS app data, [no content] (0):
* TLSv1.3 (IN), TLS app data, [no content] (0):
< HTTP/2 200 
HTTP/2 200
< server: Tengine
server: Tengine
< content-type: text/html; charset=utf-8
content-type: text/html; charset=utf-8
< content-length: 33229
content-length: 33229
< vary: Accept-Encoding
vary: Accept-Encoding
< date: Sun, 04 Dec 2022 05:42:09 GMT
date: Sun, 04 Dec 2022 05:42:09 GMT
< vary: Accept-Encoding
vary: Accept-Encoding
< x-oss-request-id: 638C3331ED63F03936E62C71
x-oss-request-id: 638C3331ED63F03936E62C71
< x-oss-cdn-auth: success
x-oss-cdn-auth: success
< accept-ranges: bytes
accept-ranges: bytes
< etag: "F540C0D57CDB57215AF11970EF4AAEF6"
etag: "F540C0D57CDB57215AF11970EF4AAEF6"
< last-modified: Wed, 23 Mar 2022 14:57:44 GMT
last-modified: Wed, 23 Mar 2022 14:57:44 GMT
< x-oss-object-type: Normal
x-oss-object-type: Normal
< x-oss-hash-crc64ecma: 8545542358272103335
x-oss-hash-crc64ecma: 8545542358272103335
< x-oss-storage-class: Standard
x-oss-storage-class: Standard
< x-oss-meta-mtime: 1648047444.796073379
x-oss-meta-mtime: 1648047444.796073379
< cache-control: no-cache
cache-control: no-cache
< content-md5: 9UDA1XzbVyFa8Rlw70qu9g==
content-md5: 9UDA1XzbVyFa8Rlw70qu9g==
< x-oss-server-time: 9
x-oss-server-time: 9
< ali-swift-global-savetime: 1670132529
ali-swift-global-savetime: 1670132529
< via: cache4.l2cn3047[67,67,200-0,M], cache67.l2cn3047[68,0], kunlun9.cn3468[83,83,200-0,M], kunlun3.cn3468[87,0]
via: cache4.l2cn3047[67,67,200-0,M], cache67.l2cn3047[68,0], kunlun9.cn3468[83,83,200-0,M], kunlun3.cn3468[87,0]
< x-cache: MISS TCP_MISS dirn:-2:-2
x-cache: MISS TCP_MISS dirn:-2:-2
< x-swift-savetime: Sun, 04 Dec 2022 05:42:09 GMT
x-swift-savetime: Sun, 04 Dec 2022 05:42:09 GMT
< x-swift-cachetime: 0
x-swift-cachetime: 0
< timing-allow-origin: *
timing-allow-origin: *
< eagleid: 7ae4079716701325292036477e
eagleid: 7ae4079716701325292036477e

<
* Connection #0 to host shanyue.tech left intact

2.6 curl -L/--location 追踪重定向

命令:curl <url> -L
示例:curl http://httpbin.org/absolute-redirect/1 -LI

sh
# -L: 追踪重定向
# -I: 只返回响应头
$ curl http://httpbin.org/absolute-redirect/1 -LI

HTTP/2 302
date: Sun, 04 Dec 2022 06:04:03 GMT
content-type: text/html; charset=utf-8
content-length: 251
location: http://httpbin.org/get
server: gunicorn/19.9.0
access-control-allow-origin: *
access-control-allow-credentials: true

HTTP/1.1 200 OK
Date: Sun, 04 Dec 2022 06:04:04 GMT
Content-Type: application/json
Content-Length: 252
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
# 可以看到,第一个响应头返回了 302 临时重定向到 http://httpbin.org/get 
# 由于 -L 追踪重定向。继续请求 http://httpbin.org/get 并返回了第二个响应头 


# 分析知乎的重定向
# 以下结果过滤了无关响应头
$ curl http://zhihu.com -LI

# 永久重定向 跳转 https 协议
HTTP/1.1 301 Moved Permanently
Content-Type: text/html
Content-Length: 182
Connection: keep-alive
Location: https://www.zhihu.com/

# 发现未登录,302 临时重定向,跳转登录页
HTTP/2 302 
server: CLOUD ELB 1.0.0
content-type: text/html; charset=utf-8
expires: 0
location: //www.zhihu.com/signin?next=%2F
cache-control: private, must-revalidate, no-cache, no-store, max-age=0  
content-length: 93

# 返回登录页信息
HTTP/2 200 
server: CLOUD ELB 1.0.0
content-type: text/html; charset=utf-8
expires: 0
cache-control: private, must-revalidate, no-cache, no-store, max-age=0  
content-length: 38114

2.7 httpie && examples 更人性化的 HTTP 命令行客户端

httpie 官网 是现代化更为流行的一个 HTTP 客户端,支持色彩、JSON 等。根据官网安装后便可以使用。

命令:http[s] [METHOD] URL [REQUEST_ITEM ...]
示例:http http://httpbin.org/get

sh
# 人性化识别 get/post
# 不带 body 默认 get
# -p: 打印
#     H: 请求头
#     B: 请求体
#     h: 响应头  还可以更简洁 直接 -h
#     b: 响应体  还可以更简洁 直接 -b
$ http http://httpbin.org/get -pH

# 携带 body 时以键值对形式存在,且自动识别为 post。但为了养成习惯,请要求自己显性写上方法
$ http http://httpbin.org/post hello=word -pH


# httpie 比 curl 方便很多,head 使用双引号,且携带 body 不需要自己写 Content-Type
  # httpie 默认: application/json 即携带 body 时默认发送 JSON 格式
  # curl 默认: application/x-www-form-urlencoded
$ http POST httpbin.org/post "a: 3" name=shanyue -pH
# -d: 携带 body
# -o /dev/null: 比特桶 忽略响应体
$ curl -X POST httpbin.org/post -H "a: 3" -H "content-type: application/json" -d '{"name": "shanyue"}' -vo /dev/null


# 发送 Form 数据给服务器端,curl/httpie 都比较方便
# -f/--form: Content-Type 设置为 application/x-www-form-urlencoded  
$ http -f POST httpbin.org/post "a: 3" name=shanyue
$ curl -X POST httpbin.org/post -H "a: 3" -d name=shanyue


# 上传文件
$ http POST httpbin.org/post < Readme.md
$ curl -X POST httpbin.org/post -H "content-type: application/json" -d @Readme.md


# multipart 上传文件
$ http --multipart httpbin.org/post a=3 b@'Readme.md' -pH
# curl 上传 multipart/form-data 很麻烦,需要将格式处理好,放在 -d 参数后,不推荐纯手敲命令。

# -F/--follow: 追踪重定向
$ http http://httpbin.org/absolute-redirect/1 -FpH