通过本文,你能明白:

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
Content-Type: application/x-www-form-urlencoded
Host: www.renren.com
Content-Length: 36

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请求头:


  1. Accept:

    text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 //浏览器告知其能解析的文件mime类型,q是权值,0<q<=1,不写的话,默认为1

  2. Accept-Charset:

    GBK,utf-8;q=0.7,*;q=0.3 //浏览器告知其能解析的字符,这里GBK是首选

  3. Accept-Encoding:

    gzip,deflate,sdch //返回文件的编码gzip压缩,Deflate或SDCH压缩

  4. Cache-Control:

    no-cache // 缓存控件,表示不进行缓存,除此之外,还有max-age,s-maxagemust-revalidate可填,具体请参数延伸阅读[1]

  5. Connection:

    keep-alive // 表示保持TPC连接,另外还有close可选,如果是短请求,即请求之后不大可能再请求数据,可以用之

  6. Referer:

    http://www.taobao.com/index_global.php // 请求发送时所在的页面,可以用这个来记录用户的访问路径,用于分析非常有效

  7. User-Agent:

    Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.168 // 浏览器标识


===============================延伸阅读================================

+关于HTTP头更详细信息可以阅读:

1. http://en.wikipedia.org/wiki/HTTP_headers

2. http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.3

3. http://blog.chinaunix.net/uid-10540984-id-3130355.html


============================ =================================


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/

============================ ==========================================