Modify error handling
This commit is contained in:
parent
bbfe5166fc
commit
80592f6625
5
build/typertext.d.ts
vendored
5
build/typertext.d.ts
vendored
|
@ -128,8 +128,11 @@ declare module Typertext.Json {
|
||||||
}
|
}
|
||||||
declare module Typertext.Json {
|
declare module Typertext.Json {
|
||||||
class JsonResponse extends GenericResponse<JsonObject> {
|
class JsonResponse extends GenericResponse<JsonObject> {
|
||||||
|
private parseSuccess;
|
||||||
static fromHttpResponse(httpResponse: Http.HttpResponse): JsonResponse;
|
static fromHttpResponse(httpResponse: Http.HttpResponse): JsonResponse;
|
||||||
constructor(status: Http.HttpResponseStatus, responseHeaderGetter?: (input: string) => string, httpResponseCode?: number, responseBody?: JsonObject);
|
static fromInvalidHttpResponse(httpResponse: Http.HttpResponse): JsonResponse;
|
||||||
|
constructor(status: Http.HttpResponseStatus, responseHeaderGetter?: (input: string) => string, httpResponseCode?: number, responseBody?: JsonObject, parseSuccess?: boolean);
|
||||||
|
public GetParseStatus(): boolean;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
declare module Typertext.Json {
|
declare module Typertext.Json {
|
||||||
|
|
|
@ -132,17 +132,17 @@ var Typertext;
|
||||||
if (xhr.status == 200) {
|
if (xhr.status == 200) {
|
||||||
callback(new Typertext.Http.HttpResponse(0 /* success */, getHeader, xhr.status, xhr.responseText));
|
callback(new Typertext.Http.HttpResponse(0 /* success */, getHeader, xhr.status, xhr.responseText));
|
||||||
} else if (xhr.status >= 400 && xhr.status < 500) {
|
} else if (xhr.status >= 400 && xhr.status < 500) {
|
||||||
throw new Typertext.Http.HttpException("The server returned an error response state", xhr.status, new Typertext.Http.HttpResponse(2 /* clientError */, getHeader, xhr.status, xhr.responseText));
|
callback(new Typertext.Http.HttpResponse(2 /* clientError */, getHeader, xhr.status, xhr.responseText));
|
||||||
} else if (xhr.status >= 500 && xhr.status < 600) {
|
} else if (xhr.status >= 500 && xhr.status < 600) {
|
||||||
throw new Typertext.Http.HttpException("The server returned an error response state", xhr.status, new Typertext.Http.HttpResponse(1 /* serverError */, getHeader, xhr.status, xhr.responseText));
|
callback(new Typertext.Http.HttpResponse(1 /* serverError */, getHeader, xhr.status, xhr.responseText));
|
||||||
} else {
|
} else {
|
||||||
throw new Typertext.Http.HttpException("An unknown error has occurred", -2, new Typertext.Http.HttpResponse(4 /* unknownError */, getHeader, xhr.status, xhr.responseText));
|
callback(new Typertext.Http.HttpResponse(4 /* unknownError */, getHeader, xhr.status, xhr.responseText));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
xhr.ontimeout = function () {
|
xhr.ontimeout = function () {
|
||||||
throw new Typertext.Http.HttpException("The server took too long to respond to our request", -1, new Typertext.Http.HttpResponse(5 /* timeout */, noop, -1, ""));
|
callback(new Typertext.Http.HttpResponse(5 /* timeout */, noop, -1, ""));
|
||||||
};
|
};
|
||||||
|
|
||||||
xhr.open(Typertext.Http.HttpMethod[method], request.ToString(), true);
|
xhr.open(Typertext.Http.HttpMethod[method], request.ToString(), true);
|
||||||
|
@ -315,8 +315,6 @@ var Typertext;
|
||||||
(function (Json) {
|
(function (Json) {
|
||||||
var HttpRequest = Typertext.Http.HttpRequest;
|
var HttpRequest = Typertext.Http.HttpRequest;
|
||||||
|
|
||||||
var HttpResponseStatus = Typertext.Http.HttpResponseStatus;
|
|
||||||
|
|
||||||
var HttpMethod = Typertext.Http.HttpMethod;
|
var HttpMethod = Typertext.Http.HttpMethod;
|
||||||
|
|
||||||
var JsonRequest = (function () {
|
var JsonRequest = (function () {
|
||||||
|
@ -336,18 +334,19 @@ var Typertext;
|
||||||
JsonRequest.prototype.RawRequest = function (method, request, postData, callback) {
|
JsonRequest.prototype.RawRequest = function (method, request, postData, callback) {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
if (typeof postData === "undefined") { postData = {}; }
|
if (typeof postData === "undefined") { postData = {}; }
|
||||||
if (typeof callback === "undefined") { callback = function (c) {
|
if (typeof callback != "function") {
|
||||||
}; }
|
this.request.RawRequest(method, request, postData, function () {
|
||||||
this.request.RawRequest(method, request, postData, function (response) {
|
});
|
||||||
if (response.GetContentType() != _this.jsonType) {
|
return;
|
||||||
callback(new Typertext.Json.JsonResponse(3 /* responseError */));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
this.request.RawRequest(method, request, postData, function (response) {
|
||||||
callback(Typertext.Json.JsonResponse.fromHttpResponse(response));
|
if (response.GetContentType() != _this.jsonType) {
|
||||||
} catch (e) {
|
callback(Typertext.Json.JsonResponse.fromInvalidHttpResponse(response));
|
||||||
throw new Typertext.Json.JsonException("Json parse exception", -1);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
callback(Typertext.Json.JsonResponse.fromHttpResponse(response));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
return JsonRequest;
|
return JsonRequest;
|
||||||
|
@ -359,13 +358,29 @@ var Typertext;
|
||||||
var Typertext;
|
var Typertext;
|
||||||
(function (Typertext) {
|
(function (Typertext) {
|
||||||
(function (Json) {
|
(function (Json) {
|
||||||
|
var HttpResponseStatus = Typertext.Http.HttpResponseStatus;
|
||||||
|
|
||||||
var JsonResponse = (function (_super) {
|
var JsonResponse = (function (_super) {
|
||||||
__extends(JsonResponse, _super);
|
__extends(JsonResponse, _super);
|
||||||
function JsonResponse(status, responseHeaderGetter, httpResponseCode, responseBody) {
|
function JsonResponse(status, responseHeaderGetter, httpResponseCode, responseBody, parseSuccess) {
|
||||||
_super.call(this, status, responseHeaderGetter, httpResponseCode, responseBody);
|
_super.call(this, status, responseHeaderGetter, httpResponseCode, responseBody);
|
||||||
|
parseSuccess = !!parseSuccess || false;
|
||||||
|
this.parseSuccess = parseSuccess;
|
||||||
}
|
}
|
||||||
JsonResponse.fromHttpResponse = function (httpResponse) {
|
JsonResponse.fromHttpResponse = function (httpResponse) {
|
||||||
return new JsonResponse(httpResponse.GetStatus(), httpResponse.GetHeader, httpResponse.GetHttpStatus(), window["JSON"].parse(httpResponse.GetContent()));
|
try {
|
||||||
|
return new JsonResponse(httpResponse.GetStatus(), httpResponse.GetHeader, httpResponse.GetHttpStatus(), window["JSON"].parse(httpResponse.GetContent()), true);
|
||||||
|
} catch (e) {
|
||||||
|
return new JsonResponse(httpResponse.GetStatus(), httpResponse.GetHeader, httpResponse.GetHttpStatus(), null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
JsonResponse.fromInvalidHttpResponse = function (httpResponse) {
|
||||||
|
return new JsonResponse(3 /* responseError */, httpResponse.GetHeader, httpResponse.GetHttpStatus());
|
||||||
|
};
|
||||||
|
|
||||||
|
JsonResponse.prototype.GetParseStatus = function () {
|
||||||
|
return this.parseSuccess;
|
||||||
};
|
};
|
||||||
return JsonResponse;
|
return JsonResponse;
|
||||||
})(Typertext.GenericResponse);
|
})(Typertext.GenericResponse);
|
||||||
|
|
File diff suppressed because one or more lines are too long
2
build/typertext.min.js
vendored
2
build/typertext.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -74,13 +74,13 @@ module Typertext.Http {
|
||||||
callback(new HttpResponse(HttpResponseStatus.success, getHeader, xhr.status, xhr.responseText));
|
callback(new HttpResponse(HttpResponseStatus.success, getHeader, xhr.status, xhr.responseText));
|
||||||
} else if (xhr.status >= 400 && xhr.status < 500) {
|
} else if (xhr.status >= 400 && xhr.status < 500) {
|
||||||
//Or fail miserably
|
//Or fail miserably
|
||||||
throw new HttpException("The server returned an error response state", xhr.status, new HttpResponse(HttpResponseStatus.clientError, getHeader, xhr.status, xhr.responseText));
|
callback(new HttpResponse(HttpResponseStatus.clientError, getHeader, xhr.status, xhr.responseText));
|
||||||
} else if (xhr.status >= 500 && xhr.status < 600) {
|
} else if (xhr.status >= 500 && xhr.status < 600) {
|
||||||
//Again
|
//Again
|
||||||
throw new HttpException("The server returned an error response state", xhr.status, new HttpResponse(HttpResponseStatus.serverError, getHeader, xhr.status, xhr.responseText));
|
callback(new HttpResponse(HttpResponseStatus.serverError, getHeader, xhr.status, xhr.responseText));
|
||||||
} else {
|
} else {
|
||||||
//And again
|
//And again
|
||||||
throw new HttpException("An unknown error has occurred", -2, new HttpResponse(HttpResponseStatus.unknownError, getHeader, xhr.status, xhr.responseText));
|
callback(new HttpResponse(HttpResponseStatus.unknownError, getHeader, xhr.status, xhr.responseText));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -88,7 +88,7 @@ module Typertext.Http {
|
||||||
//Or if it times out
|
//Or if it times out
|
||||||
xhr.ontimeout = () => {
|
xhr.ontimeout = () => {
|
||||||
//And make a big deal of the failing
|
//And make a big deal of the failing
|
||||||
throw new HttpException("The server took too long to respond to our request", -1, new HttpResponse(HttpResponseStatus.timeout, noop, -1, ""));
|
callback(new HttpResponse(HttpResponseStatus.timeout, noop, -1, ""));
|
||||||
};
|
};
|
||||||
|
|
||||||
//Now connect
|
//Now connect
|
||||||
|
|
|
@ -27,6 +27,7 @@ module Typertext.Json {
|
||||||
*
|
*
|
||||||
* @author Kegan Myers <kegan@keganmyers.com>
|
* @author Kegan Myers <kegan@keganmyers.com>
|
||||||
* @version 0.3.0
|
* @version 0.3.0
|
||||||
|
* @constructor
|
||||||
*/
|
*/
|
||||||
constructor(jsonContentType:string = "application/json") {
|
constructor(jsonContentType:string = "application/json") {
|
||||||
this.request = new HttpRequest();
|
this.request = new HttpRequest();
|
||||||
|
@ -62,19 +63,25 @@ module Typertext.Json {
|
||||||
* @param {HttpPostData} postData
|
* @param {HttpPostData} postData
|
||||||
* @param {JsonResponseHandler} callback
|
* @param {JsonResponseHandler} callback
|
||||||
*/
|
*/
|
||||||
public RawRequest(method:HttpMethod, request:HttpUrl, postData:Typertext.Http.HttpPostData = {}, callback:JsonResponseHandler = (c)=> {
|
public RawRequest(method:HttpMethod, request:HttpUrl, postData:Typertext.Http.HttpPostData = {}, callback?:JsonResponseHandler) {
|
||||||
}) {
|
//Ensure we have an executable callback
|
||||||
|
if (typeof callback != "function") {
|
||||||
|
//Make a request and ignore the response, throwing exceptions in async code can be weird
|
||||||
|
this.request.RawRequest(method, request, postData, ()=>{});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Make a full request and handle the response
|
||||||
this.request.RawRequest(method, request, postData, (response:HttpResponse)=> {
|
this.request.RawRequest(method, request, postData, (response:HttpResponse)=> {
|
||||||
//Make sure that we got the Json content type we are expecting
|
//Make sure that we got the Json content type we are expecting
|
||||||
if (response.GetContentType() != this.jsonType) {
|
if (response.GetContentType() != this.jsonType) {
|
||||||
callback(new JsonResponse(HttpResponseStatus.responseError));
|
//If not it is an invalid server response
|
||||||
|
callback(JsonResponse.fromInvalidHttpResponse(response));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
//If it is then we can just pass it straight through to the JSON response
|
||||||
callback(JsonResponse.fromHttpResponse(response));
|
callback(JsonResponse.fromHttpResponse(response));
|
||||||
} catch (e) {
|
|
||||||
throw new JsonException("Json parse exception", -1);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,13 @@ module Typertext.Json {
|
||||||
|
|
||||||
export class JsonResponse extends Typertext.GenericResponse<JsonObject> {
|
export class JsonResponse extends Typertext.GenericResponse<JsonObject> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property parseSuccess
|
||||||
|
* @type {boolean}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private parseSuccess:boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method handles converting a string into a parsed JSON object
|
* This method handles converting a string into a parsed JSON object
|
||||||
*
|
*
|
||||||
|
@ -15,7 +22,21 @@ module Typertext.Json {
|
||||||
* @returns {JsonResponse}
|
* @returns {JsonResponse}
|
||||||
*/
|
*/
|
||||||
public static fromHttpResponse(httpResponse:HttpResponse):JsonResponse {
|
public static fromHttpResponse(httpResponse:HttpResponse):JsonResponse {
|
||||||
return new JsonResponse(httpResponse.GetStatus(), httpResponse.GetHeader, httpResponse.GetHttpStatus(), window["JSON"].parse(httpResponse.GetContent()));
|
try {
|
||||||
|
return new JsonResponse(httpResponse.GetStatus(), httpResponse.GetHeader, httpResponse.GetHttpStatus(), window["JSON"].parse(httpResponse.GetContent()), true);
|
||||||
|
} catch(e) {
|
||||||
|
return new JsonResponse(httpResponse.GetStatus(), httpResponse.GetHeader, httpResponse.GetHttpStatus(), null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method handles creating an unsuccessful JSON response if the content-type is wrong
|
||||||
|
*
|
||||||
|
* @param httpResponse
|
||||||
|
* @returns {JsonResponse}
|
||||||
|
*/
|
||||||
|
public static fromInvalidHttpResponse(httpResponse:HttpResponse):JsonResponse {
|
||||||
|
return new JsonResponse(HttpResponseStatus.responseError, httpResponse.GetHeader, httpResponse.GetHttpStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,12 +47,24 @@ module Typertext.Json {
|
||||||
* @param {HttpHeaderData} responseHeaders
|
* @param {HttpHeaderData} responseHeaders
|
||||||
* @param {number} httpResponseCode
|
* @param {number} httpResponseCode
|
||||||
* @param {JsonObject} responseBody
|
* @param {JsonObject} responseBody
|
||||||
|
* @param {boolean} parseSuccess
|
||||||
*
|
*
|
||||||
* @author Kegan Myers <kegan@keganmyers.com>
|
* @author Kegan Myers <kegan@keganmyers.com>
|
||||||
* @version 0.3.0
|
* @version 0.3.0
|
||||||
*/
|
*/
|
||||||
constructor(status:HttpResponseStatus, responseHeaderGetter?:(input:string)=>string, httpResponseCode?:number, responseBody?:JsonObject) {
|
constructor(status:HttpResponseStatus, responseHeaderGetter?:(input:string)=>string, httpResponseCode?:number, responseBody?:JsonObject, parseSuccess?:boolean) {
|
||||||
super(status, responseHeaderGetter, httpResponseCode, responseBody);
|
super(status, responseHeaderGetter, httpResponseCode, responseBody);
|
||||||
|
parseSuccess = !!parseSuccess || false;
|
||||||
|
this.parseSuccess = parseSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether the parsing stage of creating creating the JSON response was successful
|
||||||
|
*
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
public GetParseStatus():boolean {
|
||||||
|
return this.parseSuccess;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,41 +4,37 @@ describe("Typertext.Json.JsonResponse", function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("fromHttpResponse", function () {
|
describe("fromHttpResponse", function () {
|
||||||
|
function hf() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
it("exists", function () {
|
it("exists", function () {
|
||||||
expect(typeof Typertext.Json.JsonResponse.fromHttpResponse).toBe("function");
|
expect(typeof Typertext.Json.JsonResponse.fromHttpResponse).toBe("function");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("handles an empty json object response", function () {
|
it("handles an empty json object response", function () {
|
||||||
function hf() {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
var inputBody = "{}",
|
var inputBody = "{}",
|
||||||
input = new Typertext.Http.HttpResponse(Typertext.Http.HttpResponseStatus.success, hf, 200, inputBody),
|
input = new Typertext.Http.HttpResponse(Typertext.Http.HttpResponseStatus.success, hf, 200, inputBody),
|
||||||
expectedBody = {},
|
expectedBody = {},
|
||||||
expectedOutput = new Typertext.Json.JsonResponse(Typertext.Http.HttpResponseStatus.success, hf, 200, expectedBody),
|
expectedOutput = new Typertext.Json.JsonResponse(Typertext.Http.HttpResponseStatus.success, hf, 200, expectedBody, true),
|
||||||
actualOutput = Typertext.Json.JsonResponse.fromHttpResponse(input);
|
actualOutput = Typertext.Json.JsonResponse.fromHttpResponse(input);
|
||||||
expect(window["JSON"].parse(inputBody)).toEqual(expectedBody);
|
expect(window["JSON"].parse(inputBody)).toEqual(expectedBody);
|
||||||
expect(window["JSON"].stringify(actualOutput)).toEqual(window["JSON"].stringify(expectedOutput));
|
expect(window["JSON"].stringify(actualOutput)).toEqual(window["JSON"].stringify(expectedOutput));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("handles an empty string", function () {
|
it("handles an empty string", function () {
|
||||||
function hf() {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
var inputBody = "",
|
var inputBody = "",
|
||||||
input = new Typertext.Http.HttpResponse(Typertext.Http.HttpResponseStatus.success, hf, 200, inputBody);
|
input = new Typertext.Http.HttpResponse(Typertext.Http.HttpResponseStatus.success, hf, 200, inputBody),
|
||||||
expect(function () {
|
expectedBody = null,
|
||||||
Typertext.Json.JsonResponse.fromHttpResponse(input);
|
expectedOutput = new Typertext.Json.JsonResponse(Typertext.Http.HttpResponseStatus.success, hf, 200, expectedBody, false),
|
||||||
|
actualOutput = Typertext.Json.JsonResponse.fromHttpResponse(input);
|
||||||
|
expect(function() {
|
||||||
|
window["JSON"].parse(inputBody)
|
||||||
}).toThrow();
|
}).toThrow();
|
||||||
|
expect(window["JSON"].stringify(actualOutput)).toEqual(window["JSON"].stringify(expectedOutput));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("handles an example server response", function () {
|
it("handles an example server response", function () {
|
||||||
function hf() {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
var inputBody = "{\"access_token\":\"0d95289cb2f54831dc435ce9274b1d1bdf8f5949\",\"expires_in\":86400," +
|
var inputBody = "{\"access_token\":\"0d95289cb2f54831dc435ce9274b1d1bdf8f5949\",\"expires_in\":86400," +
|
||||||
"\"token_type\":\"Bearer\",\"scope\":null," +
|
"\"token_type\":\"Bearer\",\"scope\":null," +
|
||||||
"\"refresh_token\":\"8a4431470af2edc3fdf747eca5f71451a3ad2d98\"}",
|
"\"refresh_token\":\"8a4431470af2edc3fdf747eca5f71451a3ad2d98\"}",
|
||||||
|
@ -50,7 +46,7 @@ describe("Typertext.Json.JsonResponse", function () {
|
||||||
"scope": null,
|
"scope": null,
|
||||||
"refresh_token": "8a4431470af2edc3fdf747eca5f71451a3ad2d98"
|
"refresh_token": "8a4431470af2edc3fdf747eca5f71451a3ad2d98"
|
||||||
},
|
},
|
||||||
expectedOutput = new Typertext.Json.JsonResponse(Typertext.Http.HttpResponseStatus.success, hf, 200, expectedBody),
|
expectedOutput = new Typertext.Json.JsonResponse(Typertext.Http.HttpResponseStatus.success, hf, 200, expectedBody, true),
|
||||||
actualOutput = Typertext.Json.JsonResponse.fromHttpResponse(input);
|
actualOutput = Typertext.Json.JsonResponse.fromHttpResponse(input);
|
||||||
expect(window["JSON"].parse(inputBody)).toEqual(expectedBody);
|
expect(window["JSON"].parse(inputBody)).toEqual(expectedBody);
|
||||||
expect(window["JSON"].stringify(actualOutput)).toEqual(window["JSON"].stringify(expectedOutput));
|
expect(window["JSON"].stringify(actualOutput)).toEqual(window["JSON"].stringify(expectedOutput));
|
||||||
|
|
Reference in a new issue