AS3获取http头部的方法
来源:互联网 发布:mac安装双系统注意事项 编辑:程序博客网 时间:2024/06/15 01:03
用AS3来解析HTTP头部
Posted on September 28, 2010 by Fdream
AS3的URLLoader本身没有提供解析HTTP头部的功能,而在应用中,我们偶尔也会需要去解析HTTP头部,可以通过HTTP头部获取一些状态信息或者一些其他数据。
幸好AS3提供了Socket类,我们可以利用Socket来模拟HTTP请求,解析HTTP头部以及返回的内容。基本原理很简单:连接服务器的80端口或者其他web端口,向服务器发送请求头,基本上和下面类似:
1. GET /web/crystal/v1.1Beta01Build011/crystal_ext-min.js HTTP/1.1
2. Accept:*/*
3. Accept-Language: zh-cn
4. User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.2; zh-CN; rv:1.9.2.10) Gecko/20100914 Firefox/3.6.10
5. Accept-Encoding: deflate
6. Host: adsfile.qq.com
7. Connection: Keep-Alive
这里需要注意的是,由于要获取请求返回的内容,因此Accept-Encoding不能写上gzip,否则你要从gzip中解压内容啦!
在发送请求完成以后就可以等待接受数据了,接受到的是字节流,因此需要decode。AS3的ByteArray对象可以从字节流中按照一定编码读取内容。由于内容的编码不一,但是header里面是可以用UTF8读取的,因此可以先一个一个字符地读出来,到header结束后在换其他编码,比如header里面指定的编码。header结束的标记是两个换行(\r\n\r\n),因此只要独到连续两个换行就代表头部已经结束了,剩下的就是内容了,用ByteArray的readMultiByte用指定编码读取出来就可以了。
具体实现的源代码可以看这里:http://code.google.com/p/fookie/source/browse/trunk/http_loader/
其实现的类为HTTPLoader,和URLLoader类似,事件是一样的,使用方法也一样,不过返回的对象是一个HTTPResponse对象,包括status、headers和body三个属性。status是请求返回的状态码,headers包含所有返回的头部,body是返回的内容,content是body的别名属性,内容和body一样。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
package net.fdream.io
{
/**
* @Script: HTTPLoader.as
* @Licence: MIT License (http://www.opensource.org/licenses/mit-license.php)
* @Author: xushengs@gmail.com
* @Website: http://code.google.com/p/fookie/
* @Version: 0.1
* @Creation: Sep 27, 2010
* @Modified: Sep 27, 2010
* @Description:
* Use socket to get HTTP headers, status and content
*
* @Usage:
* see it in HTTPLoader.fla
*
* @Events:
* They are the same with URLLoader, just list below:
* complete:
* Dispatched after all the received data is decoded
* and placed in the response property of the HTTPLoader object.
* httpStatus:
* Dispatched if response headers have received.
* ioError:
* Dispatched if a call to HTTPLoader.load()
* results in a fatal error that terminates the download.
* open:
* Dispatched when the download operation commences
* following a call to the HTTPLoader.load() method.
* progress:
* Dispatched when data is received as the download
* operation progresses.
* securityError:
* Dispatched if a call to HTTPLoader.load() attempts to
* load data from a server outside the security sandbox.
*
*/
import flash.net.Socket;
import flash.net.URLRequest;
import flash.net.URLRequestHeader;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;
import flash.events.IOErrorEvent;
import flash.events.SecurityErrorEvent;
import flash.events.ProgressEvent;
import flash.events.HTTPStatusEvent
import flash.utils.ByteArray;
public class HTTPLoader extends EventDispatcher
{
public function get userAgent():String
{
return _userAgent;
}
public function set userAgent(value:String):void
{
this._userAgent = value;
}
public function get referer():String
{
return _referer;
}
public function set referer(value:String):void
{
this._referer = value;
}
public function get response():HTTPResponse
{
return this._response;
}
// host to connect
private var _host:String = null;
// port to connect
private var _port:int = 80;
// path to load
private var _path:String = '/';
// user agent of http request
private var _userAgent:String = 'Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.10) Gecko/20100914 Firefox/3.6.10';
// referer
private var _referer:String = null;
private var _socket:Socket = new Socket();
private var _request:URLRequest = null;
private var _bytes:Array = new Array();
//private var _dispatcher:EventDispatcher = new EventDispatcher();
private var _encoding:String = 'utf-8';
// progress information
private var _bytesLoaded:int = 0;
private var _bytesTotal:int = 0;
private var _headerLength:int = 0;
// response
private var _response = {'status': 0, 'headers': {}, 'body': ''};
// url pattern
// group[1]: host
// group[2]: port
// group[3]: path
private const URL_PATTERN:RegExp = /http:\/\/([^:\/]+)(?::(\d+))?(\/.*$)/i;
/**
* constructor
*
* @param url:String
* the request to load
* @return:
* void
*/
public function HTTPLoader(request:URLRequest = null)
{
this._request = request;
}
/**
* load a request
*
* @param request:URLRequest
* the request to load
* @return:
* void
*/
public function load(request:URLRequest = null):void
{
if (request != null)
{
this._request = request;
}
if (this._request == null)
{
throw new Error('the request cannot be null');
}
// parse url
var match:Object = URL_PATTERN.exec(this._request.url);
if (match)
{
this._host = match[1];
this._port = int(match[2]) || 80;
this._path = match[3] || '/';
}
else
{
throw new Error('invalid url');
}
this._socket.addEventListener(Event.CLOSE, closeHandler);
this._socket.addEventListener(Event.CONNECT, connectHandler, false, 0, true);
this._socket.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
this._socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
this._socket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
this._socket.connect(this._host, this._port);
}
private function closeHandler(evt:Event)
{
this._response.body = parseData();
this._response = new HTTPResponse(this._response);
dispatchEvent(new Event(flash.events.Event.COMPLETE));
}
private function connectHandler(evt:Event)
{
// headers
var headers:String = this._request.method + ' ' + this._path + ' HTTP/1.0\r\nHost: ' + this._host + '\r\nAccept: */*\r\nUser-Agent: ' + this._userAgent + '\r\nAccept-Encoding: deflate\r\nAccept-Language: zh-cn\r\nConnection: Close\r\n';
if (this._referer)
{
headers += 'referer: ' + this._referer + '\r\n'
}
if (this._request.requestHeaders.length)
{
var len:int = this._request.requestHeaders.length, header:URLRequestHeader;
for (var i:int = 0; i < len; i++)
{
header = this._request.requestHeaders[i];
headers += header.name + ': ' + header.value + '\r\n';
}
}
headers += '\r\n';
// send request
this._socket.writeUTFBytes(headers);
this._socket.flush();
// dispatch open event
dispatchEvent(new Event(flash.events.Event.OPEN));
}
private function ioErrorHandler(evt:IOErrorEvent)
{
dispatchEvent(evt);
}
private function securityErrorHandler(evt:SecurityErrorEvent)
{
dispatchEvent(evt);
}
private function socketDataHandler(evt:ProgressEvent)
{
var ba:ByteArray = new ByteArray()
this._socket.readBytes(ba, 0, this._socket.bytesAvailable);
this._bytes.push(ba);
if (this._bytes.length == 1)
{
parseHeaders(ba);
_bytesLoaded = -this._headerLength;
}
_bytesLoaded += ba.length;
// dispatch progress event
dispatchEvent(new ProgressEvent(flash.events.ProgressEvent.PROGRESS, false, false, _bytesLoaded, _bytesTotal));
}
private function parseHeaders(bytes:ByteArray):void
{
var s:String = bytes.readUTFBytes(1), headers:Array = new Array(), header:String = '', headerEnded:Boolean = false, line:int = 0;
while (bytes.bytesAvailable)
{
switch (s)
{
case '\r':
break;
case '\n':
line++;
if (line == 2)
{
this._response['status'] = parseInt(headers[0].split(' ')[1]);
// dispatch progress event
dispatchEvent(new HTTPStatusEvent(flash.events.HTTPStatusEvent.HTTP_STATUS, false, false, this._response['status']));
var h:Array;
for (var i:int = 1; i < headers.length; i++)
{
h = headers[i].split(': ');
this._response['headers'][h[0]] = h[1];
switch (h[0])
{
case 'Content-Type':
var encoding:Array = h[1].split('=');
if (encoding.length > 1)
{
this._encoding = encoding[1];
}
break;
case 'Content-Length':
this._bytesTotal = parseInt(h[1]);
break;
}
}
this._headerLength = bytes.length - bytes.bytesAvailable;
headerEnded = true;
}
else
{
headers.push(header);
header = '';
}
break;
default:
line = 0;
header += s;
break;
}
if (headerEnded)
{
break;
}
else
{
s = bytes.readUTFBytes(1);
}
}
}
private function parseData():String
{
var data:String = '', ba:ByteArray, i = 0;
while (ba = this._bytes[i++])
{
data += ba.readMultiByte(ba.bytesAvailable, this._encoding)
}
return data;
}
}
}
package net.fdream.io
{
/**
* @Script: HTTPResponse.as
* @Licence: MIT License (http://www.opensource.org/licenses/mit-license.php)
* @Author: xushengs@gmail.com
* @Website: http://code.google.com/p/fookie/
* @Version: 0.1
* @Creation: Sep 27, 2010
* @Modified: Sep 27, 2010
* @Description:
* HTTPResponse Object
*/
public class HTTPResponse
{
public function get headers():Object
{
return _headers;
}
public function get status():int
{
return _status;
}
public function get body():String
{
return _body;
}
public function get content():String
{
return _body;
}
private var _headers:Object = {};
private var _status:int = 0;
private var _body:String = '';
public function HTTPResponse(response:Object)
{
this._headers = response.headers;
this._status = response.status;
this._body = response.body;
}
}
}
- AS3获取http头部的方法
- 获取http头部信息三种方法
- nginx采用遍历ngx_list_t获取源码列表中没有的http头部变量的方法
- HTTP状态码,http头部获取的Status
- Post请求鉴权中获取头部的方法
- HTTP的头部协议
- libcurl删除HTTP头部方法
- AS3 获取http 的 url、及js与as3的互调
- jq设置http头部信息和获取头部信息
- HTTP协议的头部字段
- 基于HTTP头部的注入
- as3可能能获取本地IP的几种方法
- AS3的super()方法
- User-Agent头部文件获取方法
- http头部
- AS3 利用获取指定有效颜色的方法来获取最亮颜色的坐标数值
- 最全的HTTP头部信息分析
- 网上流行的http头部解析
- 详解动态规划算法
- Windows Store apps开发[45]修改ProgressBar的颜色
- Hive安装出现的问题
- 思维定势
- 数据字典
- AS3获取http头部的方法
- IO流学习日记(一)
- 【最大子矩形】面积
- Qte库编译脚本
- Binder 学习之一
- KMP算法思考和分析
- 牛顿迭代法解非线性方程(组)
- ubuntu12.04中安装jdk
- 37.wpf程序设计指南 GradientStops 雨后彩虹