import {Attributes} from '../lang/Attributes';
import {Event} from '../lang/Event';
import {Fatal} from '../lang/Fatal';
import {Listeners} from '../lang/Listeners';
import {LoggerUtil} from '../lang/LoggerUtil';
import {ObjectBase} from '../lang/ObjectBase';
import {ObjectUtil} from '../lang/ObjectUtil';
import {NetUtil} from '../net/NetUtil';
import {HttpContentEnum} from './HttpContentEnum';
import {HttpMethodEnum} from './HttpMethodEnum';
import {HttpStatusEnum} from './HttpStatusEnum';
//==========================================================
// 页面通讯链接。
//
// @class
// @author maocy
// @version 150104
//==========================================================
export class HttpConnection extends ObjectBase {
// 异步标志
public asynchronous: boolean;
// 函数类型
public methodCd: HttpMethodEnum;
// 内容类型
public contentCd: HttpContentEnum;
// 网络地址
public url: string;
// 头信息集合
protected _heads;
// 属性集合
protected _attributes;
// 输入内容
protected _input;
// 输入数据
protected _inputData;
// 输出内容
protected _output;
// 输出数据
protected _outputData;
// 关联器
protected _linker;
// 关联句柄
protected _handle;
// 内容长度
protected _contentLength: number;
// 自由状态
protected _statusFree: boolean;
// 事件信息
protected _event;
// 加载监听器
public loadListeners: Listeners;
// 完成监听器
public completeListeners: Listeners;
//==========================================================
// 构造处理。
//==========================================================
public constructor() {
super();
// 设置属性
this.asynchronous = true;
this.methodCd = HttpMethodEnum.Get;
this.contentCd = HttpContentEnum.Binary;
this._heads = new Attributes();
this._attributes = new Attributes();
this._event = new Event(this);
this._contentLength = 0;
this._statusFree = true;
this.loadListeners = new Listeners();
this.completeListeners = new Listeners();
// 创建链接
var handle = this._handle = NetUtil.createConnection();
handle._linker = this;
handle.onreadystatechange = this.onConnectionReady;
}
//==========================================================
// 响应链接发送处理。
//==========================================================
public onConnectionSend() {
var input = this._input;
if (input) {
if (input.constructor == String) {
this._inputData = input;
this._contentLength = input.length;
} else if (input.constructor == ArrayBuffer) {
this._inputData = input;
this._contentLength = input.byteLength;
} else {
throw new Fatal(this, 'Unknown send data type.');
}
}
}
//==========================================================
// 响应链接准备处理。
//==========================================================
public onConnectionReady() {
var linker: HttpConnection = this._linker;
if (linker.asynchronous) {
var handle = linker._handle;
if (handle.readyState == HttpStatusEnum.Loaded) {
if (handle.status == 200) {
linker.setOutputData();
linker.onConnectionComplete();
} else {
LoggerUtil.fatal(linker, 'Connection failure. (url={1})', linker.url);
}
}
}
}
//==========================================================
// 响应链接完成处理。
//==========================================================
public onConnectionComplete() {
this._statusFree = true;
// 加载处理
var event = this._event;
event.connection = this;
event.content = this._outputData;
// 设置属性
var attributes = this._attributes;
var count = attributes.count();
for (var i = 0; i < count; i++) {
var name = attributes.name(i);
var value = attributes.value(i);
event[name] = value;
}
this.loadListeners.process(event);
// 完成处理
this.completeListeners.process(event);
}
//==========================================================
// 获得头信息。
//
// @param name 名称
// @return 内容
//==========================================================
public header(name) {
return this._heads.get(name);
}
//==========================================================
// 设置头信息。
//
// @param name 名称
// @param value 内容
//==========================================================
public setHeader(name, value) {
this._heads.set(name, value);
}
//==========================================================
// 设置头信息集合。
//==========================================================
public setHeaders() {
var handle = this._handle;
// 传输格式
if (this.contentCd == HttpContentEnum.Binary) {
// 二进制内容
//if (MO.Window.Browser.isBrowser(MO.EBrowser.Explorer)) {
// handle.setRequestHeader('Accept-Charset', 'x-user-defined');
// handle.responseType = 'arraybuffer';
//} else {
handle.overrideMimeType('text/plain; charset=x-user-defined');
if (this.asynchronous) {
handle.responseType = 'arraybuffer';
}
//}
} else {
// 文本内容
handle.setRequestHeader('content-type', 'application/x-www-form-urlencoded');
}
// 设置自定义头信息
var heads = this._heads;
var count = heads.count();
if (count > 0) {
// 设置头信息
for (var i = 0; i < count; i++) {
var headName = heads.name(i);
var headValue = heads.value(i);
handle.setRequestHeader(headName, headValue);
}
}
// 数据长度
//if (!MO.Window.Browser.isBrowser(MO.EBrowser.Chrome)) {
// var contentLength = o._contentLength;
// if (contentLength > 0) {
// handle.setRequestHeader('content-length', contentLength);
// }
//}
}
//==========================================================
// 设置接收信息。
//==========================================================
public setOutputData() {
var handle = this._handle;
// 传输格式
if (this.contentCd == HttpContentEnum.Binary) {
this._outputData = handle.response;
} else {
this._outputData = handle.responseText;
}
}
//==========================================================
// 获得内容。
//
// @return 内容
//==========================================================
public get content(): any {
return this._outputData;
}
//==========================================================
// 重置处理。
//==========================================================
public reset() {
// 重置链接
this._handle.abort()
// 清空属性
this._attributes.clear();
// 清空监听器
this.loadListeners.clear();
this.completeListeners.clear();
}
//==========================================================
// 同步发送页面请求。
//==========================================================
protected sendSync() {
var handle = this._handle;
handle.open(this.methodCd, this.url, false);
this.setHeaders();
handle.send(this._inputData);
this.setOutputData();
this.onConnectionComplete();
LoggerUtil.info(this, 'Send http sync request. (method={1}, url={2})', this.methodCd, this.url);
}
//==========================================================
// 异步发送页面请求。
//==========================================================
protected sendAsync() {
var handle = this._handle;
handle.open(this.methodCd, this.url, true);
this.setHeaders();
handle.send(this._inputData);
LoggerUtil.info(this, 'Send http asynchronous request. (method={1}, url={2})', this.methodCd, this.url);
}
//==========================================================
// 发送页面请求。
//
// @param url 发送地址
// @param data 发送数据
//==========================================================
public send(url, data?: any) {
// 设置参数
this.url = url;
this._input = data;
// 设置状态
this.methodCd = (data != null) ? HttpMethodEnum.Post : HttpMethodEnum.Get;
this._statusFree = false;
// 发送信息
this.onConnectionSend();
if (this.asynchronous) {
this.sendAsync();
} else {
this.sendSync();
}
return this.content;
}
//==========================================================
// 发送页面请求。
//
// @param url 发送地址
// @param data 发送数据
//==========================================================
public fetch(url, data?: any) {
this.asynchronous = false;
// 设置参数
return this.send(url, data);
}
//==========================================================
// 释放处理。
//==========================================================
public dispose() {
// 释放属性
this._heads = ObjectUtil.dispose(this._heads);
this._attributes = ObjectUtil.dispose(this._attributes);
this._event = ObjectUtil.dispose(this._event);
this._input = null;
this._inputData = null;
this._output = null;
this._outputData = null;
var handle = this._handle;
if (handle) {
handle.onreadystatechange = null;
this._handle = null;
}
// 父处理
super.dispose();
}
}