Detect JSON response in XHR and auto-parse the response.

- Part of the XMLHttpRequest level 2 API.
- Fixes a crash with the Angular2 Http service.
This commit is contained in:
Hristo Deshev
2016-02-01 16:55:31 +02:00
parent 45301aff68
commit e452aff658
2 changed files with 77 additions and 20 deletions

View File

@@ -124,6 +124,7 @@ export var test_XMLHttpRequest_contentSentAndReceivedProperly = function (done)
// <hide> // <hide>
try { try {
TKUnit.assert(result["json"]["MyVariableOne"] === "ValueOne" && result["json"]["MyVariableTwo"] === "ValueTwo", "Content not sent/received properly!"); TKUnit.assert(result["json"]["MyVariableOne"] === "ValueOne" && result["json"]["MyVariableTwo"] === "ValueTwo", "Content not sent/received properly!");
TKUnit.assert(xhr.response.json.MyVariableOne === "ValueOne" && xhr.response.json.MyVariableTwo === "ValueTwo", "Response content not parsed properly!");
done(null); done(null);
} }
catch (err) { catch (err) {
@@ -255,6 +256,44 @@ export function test_xhr_events() {
TKUnit.assertEqual(errorEventData, 'error data'); TKUnit.assertEqual(errorEventData, 'error data');
} }
export function test_xhr_responseType_text() {
const xhr = <any>new XMLHttpRequest();
const response = {
statusCode: 200,
content: {
toString: function(){ return this.raw },
raw: 'response body'
},
headers: {
"Content-Type": "text/plain"
}
}
xhr._loadResponse(response);
TKUnit.assertEqual(xhr.responseType, "text");
TKUnit.assertEqual(xhr.response, 'response body');
}
export function test_xhr_responseType_switched_to_JSON_if_header_present() {
const xhr = <any>new XMLHttpRequest();
const response = {
statusCode: 200,
content: {
toString: function(){ return this.raw },
raw: '{"data": 42}'
},
headers: {
"Content-Type": "application/json"
}
}
xhr._loadResponse(response);
TKUnit.assertEqual(xhr.responseType, "json");
TKUnit.assertEqual(xhr.response.data, 42);
}
export function test_sets_status_and_statusText(done) { export function test_sets_status_and_statusText(done) {
let xhr = new XMLHttpRequest(); let xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => { xhr.onreadystatechange = () => {

View File

@@ -21,7 +21,7 @@ export class XMLHttpRequest {
private _readyState: number; private _readyState: number;
private _status: number; private _status: number;
private _response: any; private _response: any;
private _responseText: Function; private _responseTextReader: Function;
private _headers: any; private _headers: any;
private _errorFlag: boolean; private _errorFlag: boolean;
private _responseType: string = ""; private _responseType: string = "";
@@ -53,7 +53,7 @@ export class XMLHttpRequest {
this._errorFlag = true; this._errorFlag = true;
this._response = null; this._response = null;
this._responseText = null; this._responseTextReader = null;
this._headers = null; this._headers = null;
this._status = null; this._status = null;
@@ -67,7 +67,7 @@ export class XMLHttpRequest {
public send(data?: any) { public send(data?: any) {
this._errorFlag = false; this._errorFlag = false;
this._response = null; this._response = null;
this._responseText = null; this._responseTextReader = null;
this._headers = null; this._headers = null;
this._status = null; this._status = null;
@@ -83,6 +83,17 @@ export class XMLHttpRequest {
http.request(this._options).then(r=> { http.request(this._options).then(r=> {
if (!this._errorFlag) { if (!this._errorFlag) {
this._loadResponse(r);
}
}).catch(e => {
this._errorFlag = true;
this._setReadyState(this.DONE, e);
});
}
}
private _loadResponse(r) {
this._status = r.statusCode; this._status = r.statusCode;
this._response = r.content.raw; this._response = r.content.raw;
@@ -91,19 +102,26 @@ export class XMLHttpRequest {
this._setReadyState(this.LOADING); this._setReadyState(this.LOADING);
if (this.responseType === XMLHttpRequestResponseType.empty || this._setResponseType();
this.responseType === XMLHttpRequestResponseType.text ||
this.responseType === XMLHttpRequestResponseType.json) { if (this.responseType === XMLHttpRequestResponseType.json) {
this._responseText = r.content.toString; this._responseTextReader = () => r.content.toString();
this._response = JSON.parse(this.responseText);
} else if (this.responseType === XMLHttpRequestResponseType.empty ||
this.responseType === XMLHttpRequestResponseType.text) {
this._responseTextReader = () => r.content.toString();
} }
this._setReadyState(this.DONE); this._setReadyState(this.DONE);
} }
}).catch(e => { private _setResponseType() {
this._errorFlag = true; const contentType = this.getResponseHeader('Content-Type').toLowerCase();
this._setReadyState(this.DONE, e);
}); if (contentType === 'application/json') {
this.responseType = XMLHttpRequestResponseType.json;
} else if (contentType === 'text/plain') {
this.responseType = XMLHttpRequestResponseType.text;
} }
} }
@@ -211,8 +229,8 @@ export class XMLHttpRequest {
} }
get responseText(): string { get responseText(): string {
if (types.isFunction(this._responseText)) { if (types.isFunction(this._responseTextReader)) {
return this._responseText(); return this._responseTextReader();
} }
return ""; return "";