昔我往矣

命令行http调试利器 —— curl

2018年03月6日

curl是一个相当强大的命令行版的http客户端,本文由浅入深的讲解了部分curl常用的参数和用法。在没有桌面的环境下,curl将是一把无比锋利的工具。

基本功能

简单用法

下面是一条最简单的curl用法:

$ curl https://github.com/

可以看到返回了一堆html数据,这些就是github网站首页的html代码。

传递数据

http协议有各种请求的方法(method),如,GETPOSTHEADPUT等等。这些方法curl都支持。使用-X指定请求方法,没有指定的情况下,默认使用GET请求方法。POSTPUT方法提交的数据用-d参数指定。

# GET 方法,GET参数通常放在url中
$ curl http://example.com/?page=2

# HEAD方法(不使用-X指定方法,使用-I),获取http响应的头部数据
$ curl -I http://example.com/

# POST 方法,通常用于向网站提交数据,比如提交用户名和密码用于登录认证
$ curl -X POST http://example.com/ -d "username=admin&password=123"

# PUT 方法,多用于http restful api 环境
curl -X PUT http:///example.com/user -d '{"name":"xnow"}'

头部数据

值得注意的是,在向网站发起请求分析网站返回的数据时,除了body部分,head也十分重要。比如,用于认证身份的cookie就放在request head中。

request head

我们可以使用 -H 参数修改请求head

# 修改请求中的host头部,在http 1.1中,host头部用于区别拥有相同IP,不同域名的虚拟主机。
# 使用域名请求的时候默认就有携带该head。
curl -H "host: xnow.me" http://35.201.224.126 

# 修改请求的cookie。
# 在head中,新加的 logged_in 和 dotcom_user是`github`给浏览器种下的cookie中的两个。
$ curl -H "cookie: logged_in=yes;dotcom_user=someone" https://developer.github.com/v3/

响应头部(response head)

对于网站响应的head,我们只能查看:

$ curl -I https://github.com/
HTTP/1.1 200 OK
Server: GitHub.com
Date: Mon, 05 Mar 2018 11:24:28 GMT
Content-Type: text/html; charset=utf-8
X-Request-Id: abd62496d38c658b9c68d1c7d81ae143
Set-Cookie: logged_in=no; domain=.github.com; path=/; expires=Fri, 05 Mar 2038 11:24:28 -0000; secure; HttpOnly
...

github响应的头部很大,这里只保留其中一部分,第一行HTTP/1.1 200 OK,表明网站使用http/1.1协议返回,请求被正常处理和返回。Set-Cookie头部向浏览器种cookie信息,浏览器下次请求网站的时候,就会携带这段cookie,用于验证。X-Request-Idgithub自定义的头部,非标准头部通常会以X-开头,比如X-Forward-For头部会告诉网站,客户端的真实IP地址。

总之,在http中,头部占着很重要的地位,值得好好研究。这里不详细展开。

查看响应头部(response haed)和响应数据(response body)

$ curl -i https://xnow.me

查看详细请求和响应过程

-v 可以看到curl发起请求的head和获取到的响应headbody

$ curl -v http://xnow.me # 尝试自己分辨一下吧

实操,我的网页呢?

如果你直接curl http://github.com,你会发现没有返回数据,说好的body呢?这时,你可以通过curl来分析了。

如果没有body,那我们首先使用 -I 看看head吧。

$ curl -I  http://github.com
HTTP/1.1 301 Moved Permanently
Content-length: 0
Location: https://github.com/

分析
第一行,显示使用了 HTTP/1.1 协议,返回码未301,后面的Moved Permanently解释指页面被是永久转移了。
第二行,返回的body长度为0,没有返回body,符合事实。
第三行,Location指定了页面新的地址是 https://github.com/

这就说明,页面被重定向到 https://github.com/了,那我们再访问 https://github.com/就好咯。

遇到这种情况,有没有自动跳转的,而不是这么手动判断的?方法也是有的,curl的-L 参数就可以做到。

$ curl -L http://github.com

哇塞,body又回来了,因为curl帮我们自动完成跳转。

高级一点

查看请求或响应的具体某一指标

作为运维或者开发人员,我们需要考虑网站的性能和访问速度,用curl就可以看到。

$ curl -w %{http_code} http://github.com -o /dev/null  
301   # 看到网站的返回码是301,表示网站换地址了。记得吗,前文的200标识请求成功完成

$ curl -s -w "%{time_total}\n%{size_download}\n" https://github.com/  -o /dev/null
1.553  # 请求响应的总时长,还有更详细的参数
52160  # 响应的内容大小

解释

  • -o /dev/null, 把response body部分写入文件 /dev/null (Linux黑洞设备)
  • -s 不要显示讨厌的进度条
  • -w 指定显示特定的指标,比如DNS解析耗时总耗时文件大小返回码等,可以在man curl中了解,支持二十多种返回类型。

完成认证

作为研发或者运维,你肯定遇到过浏览器弹框验证用户名和密码,例如:

http-basic-auth

这是因为开启了basic auth验证。用curl处理起来也十分简单

curl --basic --user "admin:123" http://example.com/

当年房东的路由器就是这种验证方式,最后使用这条指令,暴力破解出来了。

带https的虚拟主机

这个需求应该很少有人遇到吧。起因是,我们的nginx上有不止一个https虚拟主机,当我迁移新的https域名到这个nginx上之前,想用IP做一次验证。这就涉及到httpssni问题,sni是另一个常见的问题,这里不展开讲,sni就是为了ssl支持虚拟主机而添加的扩展。反正,如果直接curlnginx会用第一张证书验证,而不是匹配域名的证书。所以会握手出错。例如

$ curl -H "host: www.xnow.me" https://1.1.1.1/
\curl: (51) SSL: certificate subject name (*.xnow.me) does not match target host name 'www.xnow.com'

报错的意思是,我有一张 *.xnow.me的证书,和你请求的www.xnow.me不匹配。

后来,在curl 7.18.1 中,开始支持sni了,请求方法还是有点诡异的。

curl -Iv https://www.xnow.com/ --resolve "www.xnow.com:443:192.168.1.1"

总结

Linux下有很多实用好用的工具,值得深入发现和好好学习。

当前暂无评论 »

添加新评论 »