Modify error handling

master
Kegan Myers 9 years ago
parent bbfe5166fc
commit 80592f6625
  1. 5
      build/typertext.d.ts
  2. 47
      build/typertext.js
  3. 2
      build/typertext.js.map
  4. 2
      build/typertext.min.js
  5. 2
      build/typertext.min.js.map
  6. 8
      lib/Typertext/Http/HttpRequest.ts
  7. 25
      lib/Typertext/Json/JsonRequest.ts
  8. 37
      lib/Typertext/Json/JsonResponse.ts
  9. 30
      test/Typertext/Json/JsonResponse.test.js

@ -128,8 +128,11 @@ declare module Typertext.Json {
}
declare module Typertext.Json {
class JsonResponse extends GenericResponse<JsonObject> {
private parseSuccess;
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 {

@ -132,17 +132,17 @@ var Typertext;
if (xhr.status == 200) {
callback(new Typertext.Http.HttpResponse(0 /* success */, getHeader, xhr.status, xhr.responseText));
} 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) {
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 {
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 () {
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);
@ -315,8 +315,6 @@ var Typertext;
(function (Json) {
var HttpRequest = Typertext.Http.HttpRequest;
var HttpResponseStatus = Typertext.Http.HttpResponseStatus;
var HttpMethod = Typertext.Http.HttpMethod;
var JsonRequest = (function () {
@ -336,18 +334,19 @@ var Typertext;
JsonRequest.prototype.RawRequest = function (method, request, postData, callback) {
var _this = this;
if (typeof postData === "undefined") { postData = {}; }
if (typeof callback === "undefined") { callback = function (c) {
}; }
if (typeof callback != "function") {
this.request.RawRequest(method, request, postData, function () {
});
return;
}
this.request.RawRequest(method, request, postData, function (response) {
if (response.GetContentType() != _this.jsonType) {
callback(new Typertext.Json.JsonResponse(3 /* responseError */));
callback(Typertext.Json.JsonResponse.fromInvalidHttpResponse(response));
return;
}
try {
callback(Typertext.Json.JsonResponse.fromHttpResponse(response));
} catch (e) {
throw new Typertext.Json.JsonException("Json parse exception", -1);
}
callback(Typertext.Json.JsonResponse.fromHttpResponse(response));
});
};
return JsonRequest;
@ -359,13 +358,29 @@ var Typertext;
var Typertext;
(function (Typertext) {
(function (Json) {
var HttpResponseStatus = Typertext.Http.HttpResponseStatus;
var JsonResponse = (function (_super) {
__extends(JsonResponse, _super);
function JsonResponse(status, responseHeaderGetter, httpResponseCode, responseBody) {
function JsonResponse(status, responseHeaderGetter, httpResponseCode, responseBody, parseSuccess) {
_super.call(this, status, responseHeaderGetter, httpResponseCode, responseBody);
parseSuccess = !!parseSuccess || false;
this.parseSuccess = parseSuccess;
}
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;
})(Typertext.GenericResponse);

File diff suppressed because one or more lines are too long

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));
} else if (xhr.status >= 400 && xhr.status < 500) {
//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) {
//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 {
//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
xhr.ontimeout = () => {
//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

@ -27,8 +27,9 @@ module Typertext.Json {
*
* @author Kegan Myers <kegan@keganmyers.com>
* @version 0.3.0
* @constructor
*/
constructor(jsonContentType:string = "application/json") {
constructor(jsonContentType:string = "application/json") {
this.request = new HttpRequest();
this.jsonType = jsonContentType;
}
@ -62,19 +63,25 @@ module Typertext.Json {
* @param {HttpPostData} postData
* @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)=> {
//Make sure that we got the Json content type we are expecting
if (response.GetContentType() != this.jsonType) {
callback(new JsonResponse(HttpResponseStatus.responseError));
//If not it is an invalid server response
callback(JsonResponse.fromInvalidHttpResponse(response));
return;
}
try {
callback(JsonResponse.fromHttpResponse(response));
} catch (e) {
throw new JsonException("Json parse exception", -1);
}
//If it is then we can just pass it straight through to the JSON response
callback(JsonResponse.fromHttpResponse(response));
});
}
}

@ -8,6 +8,13 @@ module Typertext.Json {
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
*
@ -15,7 +22,21 @@ module Typertext.Json {
* @returns {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 {number} httpResponseCode
* @param {JsonObject} responseBody
* @param {boolean} parseSuccess
*
* @author Kegan Myers <kegan@keganmyers.com>
* @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);
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 () {
function hf() {
return "";
}
it("exists", function () {
expect(typeof Typertext.Json.JsonResponse.fromHttpResponse).toBe("function");
});
it("handles an empty json object response", function () {
function hf() {
return "";
}
var inputBody = "{}",
input = new Typertext.Http.HttpResponse(Typertext.Http.HttpResponseStatus.success, hf, 200, inputBody),
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);
expect(window["JSON"].parse(inputBody)).toEqual(expectedBody);
expect(window["JSON"].stringify(actualOutput)).toEqual(window["JSON"].stringify(expectedOutput));
});
it("handles an empty string", function () {
function hf() {
return "";
}
var inputBody = "",
input = new Typertext.Http.HttpResponse(Typertext.Http.HttpResponseStatus.success, hf, 200, inputBody);
expect(function () {
Typertext.Json.JsonResponse.fromHttpResponse(input);
input = new Typertext.Http.HttpResponse(Typertext.Http.HttpResponseStatus.success, hf, 200, inputBody),
expectedBody = null,
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();
expect(window["JSON"].stringify(actualOutput)).toEqual(window["JSON"].stringify(expectedOutput));
});
it("handles an example server response", function () {
function hf() {
return "";
}
var inputBody = "{\"access_token\":\"0d95289cb2f54831dc435ce9274b1d1bdf8f5949\",\"expires_in\":86400," +
"\"token_type\":\"Bearer\",\"scope\":null," +
"\"refresh_token\":\"8a4431470af2edc3fdf747eca5f71451a3ad2d98\"}",
@ -50,7 +46,7 @@ describe("Typertext.Json.JsonResponse", function () {
"scope": null,
"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);
expect(window["JSON"].parse(inputBody)).toEqual(expectedBody);
expect(window["JSON"].stringify(actualOutput)).toEqual(window["JSON"].stringify(expectedOutput));