Skip to content

Commit 6894a03

Browse files
committed
Changed the HttpError interface
1 parent eab6cc3 commit 6894a03

File tree

4 files changed

+131
-248
lines changed

4 files changed

+131
-248
lines changed

src/HttpError.ts

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,24 +21,48 @@ export default class HttpError extends Error
2121
statusText: string;
2222

2323
/**
24-
* The parsed response body. Can be an OperationOutcome resource, s JSON
25-
* object, a string or null.
24+
* Reference to the HTTP Response object
2625
*/
27-
body: fhirclient.JsonObject | string | null;
28-
29-
constructor(
30-
message : string = "Unknown error",
31-
statusCode: number = 0,
32-
statusText: string = "Error",
33-
body : fhirclient.JsonObject | string | null = null
34-
) {
35-
super(message);
36-
this.message = message;
26+
response: Response;
27+
28+
constructor(response: Response) {
29+
super(`${response.status} ${response.statusText}\nURL: ${response.url}`);
3730
this.name = "HttpError";
38-
this.statusCode = statusCode;
39-
this.status = statusCode;
40-
this.statusText = statusText;
41-
this.body = body;
31+
this.response = response;
32+
this.statusCode = response.status;
33+
this.status = response.status;
34+
this.statusText = response.statusText;
35+
}
36+
37+
async parse()
38+
{
39+
if (!this.response.bodyUsed) {
40+
try {
41+
const type = this.response.headers.get("Content-Type") || "text/plain";
42+
if (type.match(/\bjson\b/i)) {
43+
let body = await this.response.json();
44+
if (body.error) {
45+
this.message += "\n" + body.error;
46+
if (body.error_description) {
47+
this.message += ": " + body.error_description;
48+
}
49+
}
50+
else {
51+
this.message += "\n\n" + JSON.stringify(body, null, 4);
52+
}
53+
}
54+
else if (type.match(/^text\//i)) {
55+
let body = await this.response.text();
56+
if (body) {
57+
this.message += "\n\n" + body;
58+
}
59+
}
60+
} catch {
61+
// ignore
62+
}
63+
}
64+
65+
return this;
4266
}
4367

4468
toJSON() {
@@ -47,8 +71,7 @@ export default class HttpError extends Error
4771
statusCode: this.statusCode,
4872
status : this.status,
4973
statusText: this.statusText,
50-
message : this.message,
51-
body : this.body
74+
message : this.message
5275
};
5376
}
5477
}

src/lib.ts

Lines changed: 3 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@ function ensureNumerical({ value, code }: fhirclient.CodeValue) {
6464
*/
6565
export async function checkResponse(resp: Response): Promise<Response> {
6666
if (!resp.ok) {
67-
throw (await humanizeError(resp));
67+
const error = new HttpError(resp);
68+
await error.parse();
69+
throw error;
6870
}
6971
return resp;
7072
}
@@ -174,40 +176,6 @@ export function fetchConformanceStatement(baseUrl = "/", requestOptions?: Reques
174176
});
175177
}
176178

177-
/**
178-
* Given a response object, generates and throws detailed HttpError.
179-
* @param resp The `Response` object of a failed `fetch` request
180-
*/
181-
export async function humanizeError(resp: Response) {
182-
let msg = `${resp.status} ${resp.statusText}\nURL: ${resp.url}`;
183-
let body = null;
184-
185-
try {
186-
const type = resp.headers.get("Content-Type") || "text/plain";
187-
if (type.match(/\bjson\b/i)) {
188-
body = await resp.json();
189-
if (body.error) {
190-
msg += "\n" + body.error;
191-
if (body.error_description) {
192-
msg += ": " + body.error_description;
193-
}
194-
}
195-
else {
196-
msg += "\n\n" + JSON.stringify(body, null, 4);
197-
}
198-
}
199-
else if (type.match(/^text\//i)) {
200-
body = await resp.text();
201-
if (body) {
202-
msg += "\n\n" + body;
203-
}
204-
}
205-
} catch (_) {
206-
// ignore
207-
}
208-
209-
throw new HttpError(msg, resp.status, resp.statusText, body);
210-
}
211179

212180
/**
213181
* Walks through an object (or array) and returns the value found at the

test/HttpError.test.ts

Lines changed: 87 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,108 +1,112 @@
11
import { expect } from "@hapi/code";
22
import * as Lab from "@hapi/lab";
33
import HttpError from "../src/HttpError";
4+
import {Response} from "cross-fetch";
45

56
export const lab = Lab.script();
67
const { it, describe } = lab;
78

89
describe("HttpError", () => {
9-
it ("create with no args", () => {
10-
const error = new HttpError();
10+
it ("create from text response", async () => {
11+
const resp = new Response("Test error", {
12+
status: 400,
13+
statusText: "Bad Request (test)",
14+
headers: {
15+
"content-type": "text/plain"
16+
}
17+
});
18+
const error = new HttpError(resp);
1119
expect(error.name).to.equal("HttpError");
12-
expect(error.message).to.equal("Unknown error");
13-
expect(error.statusCode).to.equal(0);
14-
expect(error.status).to.equal(0);
15-
expect(error.statusText).to.equal("Error");
16-
expect(error.body).to.equal(null);
17-
});
18-
19-
it ("can set the message", () => {
20-
const error = new HttpError("Test Error");
21-
expect(error.name).to.equal("HttpError");
22-
expect(error.message).to.equal("Test Error");
23-
expect(error.statusCode).to.equal(0);
24-
expect(error.status).to.equal(0);
25-
expect(error.statusText).to.equal("Error");
26-
expect(error.body).to.equal(null);
20+
expect(error.message).to.equal("400 Bad Request (test)\nURL: ");
21+
expect(error.statusCode).to.equal(400);
22+
expect(error.status).to.equal(400);
23+
expect(error.statusText).to.equal("Bad Request (test)");
24+
await error.parse();
25+
expect(error.message).to.equal("400 Bad Request (test)\nURL: \n\nTest error");
2726
expect(JSON.stringify(error)).to.equal(JSON.stringify({
2827
name : "HttpError",
29-
statusCode: 0,
30-
status : 0,
31-
statusText: "Error",
32-
message : "Test Error",
33-
body : null
28+
statusCode: 400,
29+
status : 400,
30+
statusText: "Bad Request (test)",
31+
message : "400 Bad Request (test)\nURL: \n\nTest error"
3432
}));
3533
});
3634

37-
it ("can set the statusCode", () => {
38-
const error = new HttpError("Test Error", 234);
39-
expect(error.name).to.equal("HttpError");
40-
expect(error.message).to.equal("Test Error");
41-
expect(error.statusCode).to.equal(234);
42-
expect(error.status).to.equal(234);
43-
expect(error.statusText).to.equal("Error");
44-
expect(error.body).to.equal(null);
45-
expect(JSON.stringify(error)).to.equal(JSON.stringify({
46-
name : "HttpError",
47-
statusCode: 234,
48-
status : 234,
49-
statusText: "Error",
50-
message : "Test Error",
51-
body : null
52-
}));
35+
it ("parse ignores unknown mime types", async () => {
36+
const resp = new Response("Test error", {
37+
status: 400,
38+
statusText: "Bad Request (test)",
39+
headers: {
40+
"content-type": "application/pdf"
41+
}
42+
});
43+
const error = new HttpError(resp);
44+
expect(error.message).to.equal("400 Bad Request (test)\nURL: ");
45+
await error.parse();
46+
expect(error.message).to.equal("400 Bad Request (test)\nURL: ");
5347
});
5448

55-
it ("can set the statusText", () => {
56-
const error = new HttpError("Test Error", 234, "Test");
49+
it ("create from json response", async () => {
50+
const resp = new Response('{"x":"y"}', {
51+
status: 400,
52+
statusText: "Bad Request (test)",
53+
headers: {
54+
"content-type": "application/json"
55+
}
56+
});
57+
const error = new HttpError(resp);
5758
expect(error.name).to.equal("HttpError");
58-
expect(error.message).to.equal("Test Error");
59-
expect(error.statusCode).to.equal(234);
60-
expect(error.status).to.equal(234);
61-
expect(error.statusText).to.equal("Test");
62-
expect(error.body).to.equal(null);
63-
expect(JSON.stringify(error)).to.equal(JSON.stringify({
64-
name : "HttpError",
65-
statusCode: 234,
66-
status : 234,
67-
statusText: "Test",
68-
message : "Test Error",
69-
body : null
70-
}));
59+
expect(error.message).to.equal("400 Bad Request (test)\nURL: ");
60+
expect(error.statusCode).to.equal(400);
61+
expect(error.status).to.equal(400);
62+
expect(error.statusText).to.equal("Bad Request (test)");
63+
await error.parse();
64+
expect(error.message).to.equal('400 Bad Request (test)\nURL: \n\n{\n "x": "y"\n}');
7165
});
7266

73-
it ("can set the body as text", () => {
74-
const error = new HttpError("Test Error", 234, "Test", "test body");
67+
it ("create from json response having error property", async () => {
68+
const resp = new Response('{"error":"x"}', {
69+
status: 400,
70+
statusText: "Bad Request (test)",
71+
headers: {
72+
"content-type": "application/json"
73+
}
74+
});
75+
const error = new HttpError(resp);
7576
expect(error.name).to.equal("HttpError");
76-
expect(error.message).to.equal("Test Error");
77-
expect(error.statusCode).to.equal(234);
78-
expect(error.status).to.equal(234);
79-
expect(error.statusText).to.equal("Test");
80-
expect(error.body).to.equal("test body");
81-
expect(JSON.stringify(error)).to.equal(JSON.stringify({
82-
name : "HttpError",
83-
statusCode: 234,
84-
status : 234,
85-
statusText: "Test",
86-
message : "Test Error",
87-
body : "test body"
88-
}));
77+
expect(error.message).to.equal("400 Bad Request (test)\nURL: ");
78+
expect(error.statusCode).to.equal(400);
79+
expect(error.status).to.equal(400);
80+
expect(error.statusText).to.equal("Bad Request (test)");
81+
await error.parse();
82+
expect(error.message).to.equal(
83+
'400 Bad Request (test)\nURL: \nx'
84+
);
8985
});
9086

91-
it ("can set the body as object", () => {
92-
const error = new HttpError("Test Error", 234, "Test", { a: 2 });
87+
it ("create from json response having error and error_description properties", async () => {
88+
const resp = new Response('{"error":"x","error_description":"y"}', {
89+
status: 400,
90+
statusText: "Bad Request (test)",
91+
headers: {
92+
"content-type": "application/json"
93+
}
94+
});
95+
const error = new HttpError(resp);
9396
expect(error.name).to.equal("HttpError");
94-
expect(error.message).to.equal("Test Error");
95-
expect(error.statusCode).to.equal(234);
96-
expect(error.status).to.equal(234);
97-
expect(error.statusText).to.equal("Test");
98-
expect(error.body).to.equal({ a: 2 });
99-
expect(JSON.stringify(error)).to.equal(JSON.stringify({
100-
name : "HttpError",
101-
statusCode: 234,
102-
status : 234,
103-
statusText: "Test",
104-
message : "Test Error",
105-
body : { a: 2 }
106-
}));
97+
expect(error.message).to.equal("400 Bad Request (test)\nURL: ");
98+
expect(error.statusCode).to.equal(400);
99+
expect(error.status).to.equal(400);
100+
expect(error.statusText).to.equal("Bad Request (test)");
101+
await error.parse();
102+
expect(error.message).to.equal(
103+
'400 Bad Request (test)\nURL: \nx: y'
104+
);
105+
});
106+
107+
it ("parse can be called twice", async () => {
108+
const error = new HttpError(new Response());
109+
await error.parse();
110+
await error.parse();
107111
});
108112
});

0 commit comments

Comments
 (0)