Browse Source

Modify error handling

master
Kegan Myers 8 years ago
parent
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

5
build/typertext.d.ts

@ -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 {

47
build/typertext.js

@ -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);

2
build/typertext.js.map
File diff suppressed because it is too large
View File

2
build/typertext.min.js
File diff suppressed because it is too large
View File

2
build/typertext.min.js.map
File diff suppressed because it is too large
View File

8
lib/Typertext/Http/HttpRequest.ts

@ -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

25
lib/Typertext/Json/JsonRequest.ts

@ -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));
});
}
}

37
lib/Typertext/Json/JsonResponse.ts

@ -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;
}
}
}

30
test/Typertext/Json/JsonResponse.test.js

@ -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));