通过本文,你能明白:
1. HTTP 数据请的的方式GET与POST;
2. GET与POST请求体的结构;
3. 常用的HTTP请求头及其意义。
1. 带参数的普通页面请求
如果我们想向百度请求查询关键字“你好世界”并将结果页返回。
GET方式
浏览器地址栏中直接输入:http://www.baidu.com/s?wd=%C4%E3%BA%C3%CA%C0%BD%E7,wd后的内容即是我们想查询的“你好世界”,其内容请务必进行URIEncode。Encode的编写这里是GBK,这与请求的WEB服务器接收的编码有关,如果不手动进行encode,浏览器也会帮你encode的,如Chrome默认的encode是UTF-8,如果对方器恰好只支持GBK的话,那么就悲剧了。例如虽然百度GBK与UTF-8都支持,但我们以UTF-16进行编码的话,结果就是:

如果有多个数据的话,可以使用“&”进行连接,如:http://www.baidu.com/s?wd=%C4%E3%BA%C3%CA%C0%BD%E7&type=image。尽管RFC2616没有对请求的参数进行限制,每种浏览器或WEB服务器对它的限制也不同,但最安全是不超过255Bytes[http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.2.1]。
===============================延伸阅读================================
+许多web服务器或代理服务器会以日志方式记录下访问的URL,因此使用GET进行敏感数据传输是一件非常不理智的事。
+MSIE与Safari对URL长度的限制大约是2KB,Opera则是4KB,Firefox大约是8KB
。
=============================================================
POST方式——application/x-www-form-urlencoded 方式
这里我们使用Fiddler来构造请求,同上,向www.renren.com发送相同的请求。

RAW 数据如下:
POST /ajax/ShowCaptcha HTTP/1.1\r\n
Content-Type: application/x-www-form-urlencoded\r\n
Host: www.renren.com\r\n
Content-Length: 36\r\n
\r\n
email=%E5%B7%A5&password=asdasdsadas
Content-Type: application/x-www-form-urlencoded\r\n
Host: www.renren.com\r\n
Content-Length: 36\r\n
\r\n
email=%E5%B7%A5&password=asdasdsadas
这里的参数同样需要URIEncode,头与Playload必须有一行间距。MIME类型:application/x-www-form-urlencoded 是RFC2616规定的表单类型之一,其参数表示类似GET,即是key=value成对出现的,与GET方式相同,另一个是multipart/form-data(http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4),如果想要传入图片等富元素application/x-www-form-urlencoded 就无能为力了,这时需要使用multipart/form-data,下面会讲。这里顺便说说常用的HTTP请求头:
===============================延伸阅读================================
+关于HTTP头更详细信息可以阅读:
============================
=================================
POST方式——multipart/form-data 方式
同样我们向人人发送登录请求。构造的HTTP请求如下:
可以使用使用multipart/form-data比application/x-www-form-urlencoded要复杂得多,当然其也要强大许多,这里需要注意的是这种方法需要一个Boundry,通常是随机的字符串,这里是“xffxwqkxrgviutbruvdlniiluvhlqcjq”,就申明在Content-Type之后,别与发送的内容重复就好了。每两个分隔符之间就是一项表单数据,如Content-Disposition: form-data; name="email",name指的是该项的name,相当于<input name="email"/>,在后端可以使用这个name来得到数据,Content-Type: text/plain 指的是数据的类型,这里是纯文本的,如果是文件之类的就要靠这个了。例如我们抓取头像上传时的请求,如下:


绿色部分就是上传的头像的二进制数据了,注意它的MIME类型是application/octet-stream,也就是字节流信息,如果需要在Java代码里获取到这个文件,可以使用
org.apache.commons.fileupload 包。 需要注意的是,结束分隔符稍稍有点不一样,后面要多加两个dash,即"--"。如下图:

这里以我的ActionScript脚本为例子,展示手动构造HTTP multipart/form-data类型的POST请求:
public function uploadImage(bitmapData_:BitmapData):void
{
...
var urlRequest_:URLRequest = new URLRequest(_requestURL);
urlRequest_.method = URLRequestMethod.POST;
urlRequest_.contentType = "multipart/form-data; boundary=" + UploadPostHelper.getBoundary();
urlRequest_.data = UploadPostHelper.getPostData("image.jpg", jpgeEncoder_.encode(bitmapData_), urlVariables_);
...
}
UploadPostHelper.getPostData 的作用就是构造PlayLoad的主体
public static function getPostData(fileName:String, byteArray:ByteArray, parameters:Object = null):ByteArray {
...
//写入输入的参数
for(var name:String in parameters) {
postData = BOUNDARY(postData); //写入分隔符
postData = LINEBREAK(postData); // 换行
bytes = 'Content-Disposition: form-data; name="' + name + '"';
for ( i = 0; i < bytes.length; i++ ) {
postData.writeByte( bytes.charCodeAt(i) );
}
postData = LINEBREAK(postData);
postData = LINEBREAK(postData); //数据与描述信息之间必须空一行
postData.writeUTFBytes(parameters[name]);
postData = LINEBREAK(postData);
}
postData = BOUNDARY(postData);
postData = LINEBREAK(postData);
bytes = 'Content-Disposition: form-data; name="Filedata"; filename="';
for ( i = 0; i < bytes.length; i++ ) {
postData.writeByte( bytes.charCodeAt(i) ); //写入字节
}
...
//关闭playload
postData = BOUNDARY(postData);
postData = DOUBLEDASH(postData); //写入 "--" 以表示结束
return postData;
}
===============================延伸阅读================================
+关于POST提交更详细的信息可以参考:
http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1
+这里你可以找到上述UploadFileHelper的源代码:
http://labs.findsubstance.com/d/as3-upload-encode-images/
============================
==========================================