-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add handleErrorResponse to the public API
This prevents from having to manually map the received error to an Error class.
- Loading branch information
Showing
7 changed files
with
254 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
// | ||
// Copyright Inrupt Inc. | ||
// | ||
// Permission is hereby granted, free of charge, to any person obtaining a copy | ||
// of this software and associated documentation files (the "Software"), to deal in | ||
// the Software without restriction, including without limitation the rights to use, | ||
// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the | ||
// Software, and to permit persons to whom the Software is furnished to do so, | ||
// subject to the following conditions: | ||
// | ||
// The above copyright notice and this permission notice shall be included in | ||
// all copies or substantial portions of the Software. | ||
// | ||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, | ||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A | ||
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | ||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
// | ||
import { describe, it, expect } from "@jest/globals"; | ||
import { handleErrorResponse } from "./handleErrorResponse"; | ||
import { | ||
BadRequestError, | ||
BAD_REQUEST_STATUS, | ||
} from "./wellKnown/badRequestError"; | ||
import { mockResponse } from "./httpError.mock"; | ||
import ConflictError, { CONFLICT_STATUS } from "./wellKnown/conflictError"; | ||
import ForbiddenError, { FORBIDDEN_STATUS } from "./wellKnown/forbiddenError"; | ||
import GoneError, { GONE_STATUS } from "./wellKnown/goneError"; | ||
import InternalServerErrorError, { | ||
INTERNAL_SERVER_ERROR_STATUS, | ||
} from "./wellKnown/internalServerErrorError"; | ||
import MethodNotAllowedError, { | ||
METHOD_NOT_ALLOWED_STATUS, | ||
} from "./wellKnown/methodNotAllowedError"; | ||
import NotAcceptableError, { | ||
NOT_ACCEPTABLE_STATUS, | ||
} from "./wellKnown/notAcceptableError"; | ||
import NotFoundError, { NOT_FOUND_STATUS } from "./wellKnown/notFoundError"; | ||
import PreconditionFailedError, { | ||
PRECONDITION_FAILED_STATUS, | ||
} from "./wellKnown/preconditionFailedError"; | ||
import TooManyRequestsError, { | ||
TOO_MANY_REQUESTS_STATUS, | ||
} from "./wellKnown/tooManyRequestsError"; | ||
import UnauthorizedError, { | ||
UNAUTHORIZED_STATUS, | ||
} from "./wellKnown/unauthorizedError"; | ||
import UnsupportedMediaTypeError, { | ||
UNSUPPORTED_MEDIA_TYPE_STATUS, | ||
} from "./wellKnown/unsupportedMediaTypeError"; | ||
|
||
describe("handleErrorResponse", () => { | ||
it.each([ | ||
[BAD_REQUEST_STATUS, BadRequestError], | ||
[CONFLICT_STATUS, ConflictError], | ||
[FORBIDDEN_STATUS, ForbiddenError], | ||
[GONE_STATUS, GoneError], | ||
[INTERNAL_SERVER_ERROR_STATUS, InternalServerErrorError], | ||
[METHOD_NOT_ALLOWED_STATUS, MethodNotAllowedError], | ||
[NOT_ACCEPTABLE_STATUS, NotAcceptableError], | ||
[NOT_FOUND_STATUS, NotFoundError], | ||
[PRECONDITION_FAILED_STATUS, PreconditionFailedError], | ||
[TOO_MANY_REQUESTS_STATUS, TooManyRequestsError], | ||
[UNAUTHORIZED_STATUS, UnauthorizedError], | ||
[UNSUPPORTED_MEDIA_TYPE_STATUS, UnsupportedMediaTypeError], | ||
])("maps %i status to %s class", (responseStatus, errorClass) => { | ||
const response = mockResponse({ status: responseStatus }); | ||
const error = handleErrorResponse( | ||
response, | ||
"Some response body", | ||
"Some error message", | ||
); | ||
expect(error).toBeInstanceOf(errorClass); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
// | ||
// Copyright Inrupt Inc. | ||
// | ||
// Permission is hereby granted, free of charge, to any person obtaining a copy | ||
// of this software and associated documentation files (the "Software"), to deal in | ||
// the Software without restriction, including without limitation the rights to use, | ||
// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the | ||
// Software, and to permit persons to whom the Software is furnished to do so, | ||
// subject to the following conditions: | ||
// | ||
// The above copyright notice and this permission notice shall be included in | ||
// all copies or substantial portions of the Software. | ||
// | ||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, | ||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A | ||
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | ||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
// | ||
import { ClientHttpError } from "./httpError"; | ||
import BadRequestError, { | ||
BAD_REQUEST_STATUS, | ||
} from "./wellKnown/badRequestError"; | ||
import ConflictError, { CONFLICT_STATUS } from "./wellKnown/conflictError"; | ||
import ForbiddenError, { FORBIDDEN_STATUS } from "./wellKnown/forbiddenError"; | ||
import GoneError, { GONE_STATUS } from "./wellKnown/goneError"; | ||
import InternalServerErrorError, { | ||
INTERNAL_SERVER_ERROR_STATUS, | ||
} from "./wellKnown/internalServerErrorError"; | ||
import MethodNotAllowedError, { | ||
METHOD_NOT_ALLOWED_STATUS, | ||
} from "./wellKnown/methodNotAllowedError"; | ||
import NotAcceptableError, { | ||
NOT_ACCEPTABLE_STATUS, | ||
} from "./wellKnown/notAcceptableError"; | ||
import NotFoundError, { NOT_FOUND_STATUS } from "./wellKnown/notFoundError"; | ||
import PreconditionFailedError, { | ||
PRECONDITION_FAILED_STATUS, | ||
} from "./wellKnown/preconditionFailedError"; | ||
import TooManyRequestsError, { | ||
TOO_MANY_REQUESTS_STATUS, | ||
} from "./wellKnown/tooManyRequestsError"; | ||
import UnauthorizedError, { | ||
UNAUTHORIZED_STATUS, | ||
} from "./wellKnown/unauthorizedError"; | ||
import UnsupportedMediaTypeError, { | ||
UNSUPPORTED_MEDIA_TYPE_STATUS, | ||
} from "./wellKnown/unsupportedMediaTypeError"; | ||
|
||
/** | ||
* Map an HTTP error response to one of the Error classes exported by this library. | ||
* | ||
* @example | ||
* ```ts | ||
* const response = await fetch("https://example.org/resource"); | ||
* if (!response.ok) { | ||
* const responseBody = await response.text(); | ||
* throw handleErrorResponse(response, responseBody, "Fetch got error response"); | ||
* } | ||
* ``` | ||
* | ||
* @param responseMetadata the response metadata | ||
* @param responseBody the response body | ||
* @param message the error message | ||
* @returns an instance of the ClientHttpError subclass matching the response metadata status. | ||
* If the response status is unkown, the generic ClientHttpError class is used. | ||
* @since unreleased | ||
*/ | ||
export function handleErrorResponse( | ||
responseMetadata: { | ||
status: number; | ||
statusText: string; | ||
headers: Headers; | ||
url: string; | ||
}, | ||
responseBody: string, | ||
message: string, | ||
): ClientHttpError { | ||
switch (responseMetadata.status) { | ||
case BAD_REQUEST_STATUS: | ||
return new BadRequestError(responseMetadata, responseBody, message); | ||
case CONFLICT_STATUS: | ||
return new ConflictError(responseMetadata, responseBody, message); | ||
case FORBIDDEN_STATUS: | ||
return new ForbiddenError(responseMetadata, responseBody, message); | ||
case GONE_STATUS: | ||
return new GoneError(responseMetadata, responseBody, message); | ||
case INTERNAL_SERVER_ERROR_STATUS: | ||
return new InternalServerErrorError( | ||
responseMetadata, | ||
responseBody, | ||
message, | ||
); | ||
case METHOD_NOT_ALLOWED_STATUS: | ||
return new MethodNotAllowedError(responseMetadata, responseBody, message); | ||
case NOT_ACCEPTABLE_STATUS: | ||
return new NotAcceptableError(responseMetadata, responseBody, message); | ||
case NOT_FOUND_STATUS: | ||
return new NotFoundError(responseMetadata, responseBody, message); | ||
case PRECONDITION_FAILED_STATUS: | ||
return new PreconditionFailedError( | ||
responseMetadata, | ||
responseBody, | ||
message, | ||
); | ||
case TOO_MANY_REQUESTS_STATUS: | ||
return new TooManyRequestsError(responseMetadata, responseBody, message); | ||
case UNAUTHORIZED_STATUS: | ||
return new UnauthorizedError(responseMetadata, responseBody, message); | ||
case UNSUPPORTED_MEDIA_TYPE_STATUS: | ||
return new UnsupportedMediaTypeError( | ||
responseMetadata, | ||
responseBody, | ||
message, | ||
); | ||
default: | ||
return new ClientHttpError(responseMetadata, responseBody, message); | ||
} | ||
} | ||
|
||
export default handleErrorResponse; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// | ||
// Copyright Inrupt Inc. | ||
// | ||
// Permission is hereby granted, free of charge, to any person obtaining a copy | ||
// of this software and associated documentation files (the "Software"), to deal in | ||
// the Software without restriction, including without limitation the rights to use, | ||
// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the | ||
// Software, and to permit persons to whom the Software is furnished to do so, | ||
// subject to the following conditions: | ||
// | ||
// The above copyright notice and this permission notice shall be included in | ||
// all copies or substantial portions of the Software. | ||
// | ||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, | ||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A | ||
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | ||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
// | ||
|
||
import { PROBLEM_DETAILS_MIME } from "./problemDetails"; | ||
|
||
export const mockResponse = ({ | ||
body, | ||
status, | ||
statusText, | ||
headers, | ||
}: { | ||
body?: string; | ||
status?: number; | ||
statusText?: string; | ||
headers?: Headers; | ||
responseUrl?: string; | ||
} = {}): Response => { | ||
const response = new Response(body ?? undefined, { | ||
status: status ?? 400, | ||
statusText: statusText ?? "Bad Request", | ||
headers: | ||
headers ?? | ||
new Headers({ | ||
"Content-Type": PROBLEM_DETAILS_MIME, | ||
}), | ||
}); | ||
return response; | ||
}; | ||
|
||
export default mockResponse; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters