Skip to content

Commit

Permalink
feat!: parse json error response
Browse files Browse the repository at this point in the history
Signed-off-by: Boris Tomic <[email protected]>

BREAKING CHANGE: Error response is parsed as JSON if response headers
have content-type application/json and if it's possible to parse the
data as JSON. Otherwise response will be retuned as string or default
response will be returned as empty string.
  • Loading branch information
boristomic committed Dec 4, 2023
1 parent 808a54b commit c450977
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 19 deletions.
55 changes: 38 additions & 17 deletions src/wrapper.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,24 +119,45 @@ describe('RequestWrapper', function() {
expect(requestArgument.httpsAgent).to.eql(agents.httpsAgent);
});

it('should throw error when response code is 400 or above', async () => {
requestGetStub.restore();
nock('http://very.host.io:443')
.get('/purchases/1/content')
.reply(400, { replyText: 'Unknown route' });
context('error responses', () => {
it('should return JSON in EscherRequestError if response data is json parsable', async () => {
requestGetStub.restore();
nock('http://very.host.io:443')
.get('/purchases/1/content')
.reply(400, { replyText: 'Unknown route' }, { 'Content-Type': 'application/json; charset=utf-8' });

try {
await wrapper.send();
throw new Error('Error should have been thrown');
} catch (err) {
const error = err as EscherRequestError;
expect(error).to.be.an.instanceof(EscherRequestError);
expect(error.message).to.eql('Error in http response (status: 400)');
expect(error.code).to.eql(400);
expect(error.data).to.eql(JSON.stringify({ replyText: 'Unknown route' }));
}
try {
await wrapper.send();
throw new Error('Error should have been thrown');
} catch (err) {
const error = err as EscherRequestError;
expect(error).to.be.an.instanceof(EscherRequestError);
expect(error.message).to.eql('Error in http response (status: 400)');
expect(error.code).to.eql(400);
expect(error.data).to.eql({ replyText: 'Unknown route' });
}
});

it('should return text and not fail parsing response data if wrong content-type headers are set', async () => {
requestGetStub.restore();
nock('http://very.host.io:443')
.get('/purchases/1/content')
.reply(500, 'Unexpected Error', { 'Content-Type': 'application/json; charset=utf-8' });

try {
await wrapper.send();
throw new Error('Error should have been thrown');
} catch (err) {
const error = err as EscherRequestError;
expect(error).to.be.an.instanceof(EscherRequestError);
expect(error.message).to.eql('Error in http response (status: 500)');
expect(error.code).to.eql(500);
expect(error.data).to.eql('Unexpected Error');
}
});
});


describe('when empty response is allowed', function() {
beforeEach(function() {
extendedRequestOptions.allowEmptyResponse = true;
Expand Down Expand Up @@ -216,7 +237,7 @@ describe('RequestWrapper', function() {
expect(error).to.be.an.instanceOf(EscherRequestError);
expect(error.code).to.eql(404);
expect(error.message).to.eql('Error in http response (status: 404)');
expect(error.data).to.eql(JSON.stringify({ replyText: '404 Not Found' }));
expect(error.data).to.eql({ replyText: '404 Not Found' });
}
});
});
Expand Down Expand Up @@ -340,7 +361,7 @@ describe('RequestWrapper', function() {
expect(error).to.be.an.instanceOf(EscherRequestError);
expect(error.code).to.eql(404);
expect(error.message).to.eql('Error in http response (status: 404)');
expect(error.data).to.eql(JSON.stringify({ replyText: '404 Not Found' }));
expect(error.data).to.eql({ replyText: '404 Not Found' });
}
});

Expand Down
16 changes: 14 additions & 2 deletions src/wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,22 @@ export class RequestWrapper {
code: error.response.status,
reply_text: (error.response?.data || '')
}));
let data = '';
if (error.response != null &&
this.isJsonResponse(error.response) &&
error.response.data != null &&
typeof error.response.data === 'string') {
try {
data = JSON.parse(error.response.data);
} catch (_) {
data = error.response.data;
}
}

throw new EscherRequestError(
'Error in http response (status: ' + error.response.status + ')',
error.response.status,
(error.response?.data || '') as string
data
);
} else {
if (!axios.isCancel(error)) {
Expand Down Expand Up @@ -142,7 +154,7 @@ export class RequestWrapper {
};
}

private isJsonResponse(response: TransformedResponse) {
private isJsonResponse<T extends TransformedResponse | AxiosResponse>(response: T) {
return response.headers['content-type'] &&
response.headers['content-type'].indexOf('application/json') !== -1;
}
Expand Down

0 comments on commit c450977

Please sign in to comment.