HTTP

1.5.2 HTTP

HTTP(HyperText Transport Protocol)即超文本传输协议,它详细规定了浏览器和万维网服务器之间互相通信的规则,是通过因特网传送万维网文档的数据传送协议。Rfc2612(http://www.ietf.org/rfc/rfc2616.txt)使用了 176 页的“天书”来描述这个协议。微信后台在向我们的公众平台服务器发消息的时候(图 1-1 中的第 2 步)使用的就是 HTTP 协议。看起来我们好像遇到了大麻烦,幸运的是我们并不需要看完这些文档才能开始使用它。在使用 PHP 来做 HTTP 的服务端的时候,Apache 为我们解析好了大部分的协议,并提供了非常方便的方法以供我们获取需要的信息。其中,我们需要关心的是两个全局变量 $_GET 和 $HTTP_RAW_POST_DATA。Apache 解析好请求中的 HTTP 协议,把请求中 get 数据和 post 变量写入 $_GET 和 $HTTP_RAW_POST_DATA 变量中。我们只要直接使用 $_GET 和 $HTTP_RAW_POST_DATA 就能取到微信后台传给我们的数据。

笔者在 meiri10futu 的部署机器上运行 tcpdump 抓包, 图 1-31 是抓到并用 wireshark 分析的一个完整的请求和返回包。
公众平台服务器的HTTP 请求和返回包
图1-31 公众平台服务器的HTTP 请求和返回包

图 1-31 所示的数据中,“HTTP/1.1 200 OK”之前的部分是微信后台发给公众账号服务器的请求(图 1-1 中的第 2 步),之后的部分是公众账号服务器返回给微信后台的数据。我们现在重点关注请求部分,先把这部分数据以文本形式粘贴到下面:

POST
/interface.php?signature=771f6bd01508e46b02061b0a1330a6ad67e1ad77&timestamp=1364458805&nonce=1364226029 HTTP/1.0
User-Agent: Mozilla/4.0
Accept: */*
Host: 112.124.53.50
Content-Type: text/xml
Content-Length: 276
Pragma: no-cache
Connection: Keep-Alive
<xml><ToUserName><![CDATA[gh_a8b0ebbe91f5]]></ToUserName>
<FromUserName><![CDATA[owI97jpNpdfSpOsR9kG97g_wRtvY]]></FromUserName>
<CreateTime>1364458805</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[...]]></Content>
<MsgId>5860305944314258860</MsgId>
</xml>

请求分为头部(head)和正文(body)两部分,数据之间用一个空行分割(实际上是两个“\r\n”),即上面的“Keep-Alive”下面的空行之后的数据为 body,之前的部分为 head。接下来我们来看 GET 数据和 POST 数据在哪里。

(1) HTTP 请求中的 GET 数据

注意上面的请求数据中的第一行中如下的数据:
signature=771f6bd01508e46b02061b0a1330a6ad67e1ad77&timestamp=1364458805&nonce=1364226029
这些用“&”分隔的字符串就是 GET 数据,我们把用“&”分割之后的字符串列出来:
❑ signature=771f6bd01508e46b02061b0a1330a6ad67e1ad77
❑ timestamp=1364458805
❑ nonce=1364226029
这样看起来就非常清楚了,等号左边是 GET 数据的 key,右边是 GET 数据的 value,具体如何在 PHP 程序中获取这些 GET 数据,等讲完 POST 数据之后会有一个统一的例子。

(2) HTTP 请求中 POST 数据

上面请求中的 body 部分就是 POST 数据,POST 数据和 GET 数据不同,它不会有 key 值。POST 数据一般都比较大,GET 数据往往比较小。下面的程序展示了如何获取 GET 数据和 POST 数据。我们把 test2.php 的内容改成如下形式:

<?php
file_put_contents("C:\\AppServ\\tmp.txt", var_export($_GET, true), FILE_APPEND);
file_put_contents("C:\\AppServ\\tmp.txt", "\n", FILE_APPEND);
file_put_contents("C:\\AppServ\\tmp.txt", var_export($HTTP_RAW_POST_DATA, true), FILE_APPEND);
?>

然后我们使用 Fiddler 的 Request Bilder 向 test2.php 发一个 POST 请求,请求中带的 GET 数据及 POST 数据和上面的示例一样,如图 1-32 所示。
用 Fiddler 向 test2.php 发 POST 请求
图1-32 用 Fiddler 向 test2.php 发 POST 请求

然后查看 tmp.txt 中的输出,如图 1-33 所示。
GET 和 POST 数据在文本中的输出
图1-33 GET 和 POST 数据在文本中的输出


注意 在 Fiddler 中输入 GET 数据时不是在 Request Header 输入框中输入,而是在请求 URL 后先输入一个问号,然后输入所有的 GET 字符串。

可以看到,$_GET 是一个数组;key 是各个 GET 数据的 key;$HTTP_RAW_POST_DATA 是一个字符串,包含 body 的所有内容。在设置这些变量的同时,Apache 还为我们设置了一个 $_POST 变量,它是用来存前台 HTML 的 form 表达提交的数据,本书使用不到。大家不要误以为 $_POST 变量是我们想要的 POST 数据,一定要区分开。


注意 我们在这里没有使用 editplus 来打开 tmp.txt,而是用的写字板。如果你试了用 editplus 打开的话会发现,脚本中我们特意输出和 var_export 自动输出的“\n”都没有当成换行符来显示,使得格式很难看。这是因为当文件中既有“\r\n”又有“\n”时,editplus 会自动选择其中的一种作为换行符,而忽略其他的方式。在打开 tmp.txt 时 editplus 就选择了 HTTP 的 body 中的“\r\n”作为换行符而忽略了“\n”。

在这一小节中我们用到了三个非常有用的工具:
1) tcpdump 是一个 Linux 上的抓包命令,有非常多的选项和表达式。可以结合自己的需求,使用相应的选项和表达式来抓取需要的网络包。
2) wireshark 是一个 Windows 上的抓包工具。它的功能和 tcpdump 是一样的,但是它的优点在于其图形化界面,对数据包的可视化做得非常好,同时也能打开 tcpdump 的数据包文件。我就喜欢用 tcpdump 在 Linux 机器上抓包之后再到 Windows 上用 wireshark 打开来分析。
3) fiddler 是一个非常强大的 HTTP 调试代理,它能够记录并检查所有你的电脑和互联网之间的 HTTP 通信,设置断点,查看 fiddle 中所有“进出”的数据(指 cookie、HTML,JS,CSS 等文件,这些都可以让你胡乱修改)。我们这里使用它来代替 Chrome 浏览器构造请求包,因为 Chrome 浏览器不能让我们灵活地自定义 GET 数据和 POST 数据。请读者到 fiddler 的官网(http://fiddler2.com/get-fiddler)下载 fiddler 并安装好,稍后还会用到它。

使用好这些工具对于自己的工作和学习有非常大的帮助。有兴趣的读者可以到网络上搜索这些工具的高级教程。

HTTP 协议相关的内容非常多,本书中需要用到的就只有这些了。读者如果有兴趣的话可以专门找一些介绍 HTTP 协议的资料进行学习,或者认真阅读一下 rfc2612

下一节 1.5.3 XML
上一节 1.5.1 PHP
返回微信公众平台应用开发实战

天香空城微信二维码
关注 天香空城 微信号 ulisse 或扫描二维码,可以了解微信营销书籍
微信营销书评
微信公众平台开发源码

返回微信营销