Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception Handling enhancement #429

Merged
merged 8 commits into from
Jul 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 22 additions & 18 deletions app/Exceptions/Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public function render($request, \Throwable $e): JsonResponse|Response
->json([
'status' => 500,
'type' => 'ConnectionException',
'message' => 'Failed to communicate with Redis.',
'message' => 'Failed to communicate with the Redis server',
'error' => env('APP_DEBUG') ? $e->getMessage() : null,
'report_url' => env('GITHUB_REPORTING', true) ? (string) $githubReport : null
], 500);
Expand Down Expand Up @@ -137,8 +137,8 @@ public function render($request, \Throwable $e): JsonResponse|Response
return response()
->json([
'status' => $e->getCode(),
'type' => 'BadResponseException',
'message' => 'Jikan is being rate limited by MyAnimeList',
'type' => 'RateLimitException',
'message' => 'Jikan is being rate limited by MyAnimeList.',
'error' => $e->getMessage()
], $e->getCode());
case 403:
Expand All @@ -152,38 +152,42 @@ public function render($request, \Throwable $e): JsonResponse|Response

return response()
->json([
'status' => $e->getCode(),
'type' => 'BadResponseException',
'message' => 'Jikan failed to connect to MyAnimeList.net. MyAnimeList.net may be down/unavailable, refuses to connect or took too long to respond.',
'status' => 500,
'type' => 'UpstreamException',
'message' => 'Request to MyAnimeList.net failed. MyAnimeList.net may be down/unavailable, refuses to connect or took too long to respond. Please try again later.',
'error' => $e->getMessage()
], 503);
], 500);
default:
return response()
->json([
'status' => $e->getCode(),
'type' => 'BadResponseException',
'message' => 'Something went wrong, please try again later',
'message' => 'Something went wrong, please try again later.',
'error' => $e->getMessage()
], $e->getCode());
}
}

if ($e instanceof TimeoutException) {
event(new SourceHeartbeatEvent(SourceHeartbeatEvent::BAD_HEALTH, $e->getCode()));

return response()
->json([
'status' => 408,
'type' => 'TimeoutException',
'message' => 'Request to MyAnimeList.net timed out (' .env('SOURCE_TIMEOUT', 5) . ' seconds)',
'status' => 500,
'type' => 'UpstreamException',
'message' => 'Request to MyAnimeList.net timed out (' .env('SOURCE_TIMEOUT', 5) . ' seconds). Please try again later.',
'error' => $e->getMessage()
], 408);
], 500);
}

if ($e instanceof TransportException) {
event(new SourceHeartbeatEvent(SourceHeartbeatEvent::BAD_HEALTH, $e->getCode()));

return response()
->json([
'status' => 500,
'type' => 'TransportException',
'message' => 'Request to MyAnimeList.net has failed. The upstream server has returned a non-successful status code.',
'type' => 'UpstreamException',
'message' => 'Request to MyAnimeList.net failed. MyAnimeList.net may be down/unavailable, refuses to connect or took too long to respond. Please try again later.',
'error' => $e->getMessage()
], 500);
}
Expand All @@ -193,11 +197,11 @@ public function render($request, \Throwable $e): JsonResponse|Response

return response()
->json([
'status' => $e->getCode(),
'type' => 'BadResponseException',
'message' => 'Jikan failed to connect to MyAnimeList.net. MyAnimeList.net may be down/unavailable, refuses to connect or took too long to respond. Retry the request!',
'status' => 500,
'type' => 'UpstreamException',
'message' => 'Request to MyAnimeList.net failed. MyAnimeList.net may be down/unavailable, refuses to connect or took too long to respond. Please try again later.',
'error' => $e->getMessage()
], 503);
], 500);
}

// Bad REST API requests
Expand Down
51 changes: 24 additions & 27 deletions config/swagger-lume.php
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@
'API_DESCRIPTION' => str_replace("\r\n", "\n", <<<EOF
[Jikan](https://jikan.moe) is an **Unofficial** MyAnimeList API.
It scrapes the website to satisfy the need for a complete API - which MyAnimeList lacks.

# Information

⚡ Jikan is powered by it's awesome backers - 🙏 [Become a backer](https://www.patreon.com/jikan)
Expand All @@ -212,10 +212,12 @@

| Duration | Requests |
|----|----|
| Monthly | **Unlimited** |
| Daily | **Unlimited** |
| Per Minute | 60 requests |
| Per Second | 3 requests |

Note: It's still possible to get rate limited from MyAnimeList.net instead.


## JSON Notes
- Any property (except arrays or objects) whose value does not exist or is undetermined, will be `null`.
Expand All @@ -226,23 +228,18 @@
## Caching
By **CACHING**, we refer to the data parsed from MyAnimeList which is stored temporarily on our servers to provide better API performance.

All requests, by default are cached for **24 hours** except the following endpoints which have their own unique cache **Time To Live**.

| Request | TTL |
| ---- | ---- |
| All (Default) | 24 hours |

All requests are cached for **24 hours**.

The following response headers will detail cache information.

| Header | Remarks |
| ---- | ---- |
| `Expires` | Cache expiry date |
| `Last-Modified` | Cache set date |
| `X-Request-Fingerprint` | Unique request fingerprint |

| `X-Request-Fingerprint` | Unique request fingerprint (only for cachable requests, not queries) |

Note: Caching headers will only be available on single resource requests and their child endpoints. e.g `/anime/1`, `/anime/1/relations`.

Note: `X-Request-Fingerprint` will only be available on single resource requests and their child endpoints. e.g `/anime/1`, `/anime/1/relations`.
They won't be available on pages which perform queries, like /anime, or /top/anime, etc.

## Allowed HTTP(s) requests
Expand All @@ -252,26 +249,26 @@

## HTTP Responses

| HTTP Status | Remarks |
| ---- | ---- |
| `200 - OK` | The request was successful |
| `304 - Not Modified` | You have the latest data (Cache Validation response) |
| `400 - Bad Request` | You've made an invalid request. Recheck documentation |
| `404 - Not Found` | The resource was not found or MyAnimeList responded with a `404` |
| `405 - Method Not Allowed` | Requested Method is not supported for resource. Only `GET` requests are allowed |
| `429 - Too Many Request` | You are being rate limited by Jikan or MyAnimeList is rate-limiting our servers (specified in the error response) |
| `500 - Internal Server Error` | Something is not working on our end. If you see an error response with a `report_url` URL, please click on it to open an auto-generated GitHub issue |
| `503 - Service Unavailable` | The service has broke. |
All error responses are accompanied by a JSON Error response.

| Exception | HTTP Status | Remarks |
| ---- | ---- | ---- |
| N/A | `200 - OK` | The request was successful |
| N/A | `304 - Not Modified` | You have the latest data (Cache Validation response) |
| `BadRequestException|ValidationException` | `400 - Bad Request` | You've made an invalid request. Recheck documentation |
| `BadResponseException` | `404 - Not Found` | The resource was not found or MyAnimeList responded with a `404` |
| `BadRequestException` | `405 - Method Not Allowed` | Requested Method is not supported for resource. Only `GET` requests are allowed |
| `RateLimitException` | `429 - Too Many Request` | You are being rate limited by Jikan or MyAnimeList is rate-limiting our servers (specified in the error response) |
| `UpstreamException|ParserException`, Multiple | `500 - Internal Server Error` | Something didn't work. Try again later. If you see an error response with a `report_url` URL, please click on it to open an auto-generated GitHub issue |

## JSON Error Response

```json
{
"status": 404,
"type": "BadResponseException",
"message": "Resource does not exist",
"error": "Something Happened",
"status": 500,
"type": "InternalException",
"message": "Exception Message",
"error": "Exception Trace",
"report_url": "https://github.com..."
}
```
Expand All @@ -282,7 +279,7 @@
| `type` | Thrown Exception |
| `message` | Human-readable error message |
| `error` | Error response and trace from the API |
| `report_url` | Clicking this would redirect you to a generated GitHub issue. ℹ It's only returned on a parser error. |
| `report_url` | Clicking this would redirect you to a generated GitHub issue |


## Cache Validation
Expand Down
4 changes: 1 addition & 3 deletions storage/api-docs/api-docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"openapi": "3.0.0",
"info": {
"title": "Jikan API",
"description": "[Jikan](https://jikan.moe) is an **Unofficial** MyAnimeList API.\nIt scrapes the website to satisfy the need for a complete API - which MyAnimeList lacks.\n\n# Information\n\n⚡ Jikan is powered by it's awesome backers - 🙏 [Become a backer](https://www.patreon.com/jikan)\n\n## Rate Limiting\n\n| Duration | Requests |\n|----|----|\n| Monthly | **Unlimited** |\n| Per Minute | 60 requests |\n| Per Second | 3 requests |\n\n\n## JSON Notes\n- Any property (except arrays or objects) whose value does not exist or is undetermined, will be `null`.\n- Any array or object property whose value does not exist or is undetermined, will be empty.\n- Any `score` property whose value does not exist or is undetermined, will be `0`.\n- All dates and timestamps are returned in [ISO8601](https://en.wikipedia.org/wiki/ISO_8601) format and in UTC timezone\n\n## Caching\nBy **CACHING**, we refer to the data parsed from MyAnimeList which is stored temporarily on our servers to provide better API performance.\n\nAll requests, by default are cached for **24 hours** except the following endpoints which have their own unique cache **Time To Live**. \n\n| Request | TTL |\n| ---- | ---- |\n| All (Default) | 24 hours |\n\n\nThe following response headers will detail cache information.\n\n| Header | Remarks |\n| ---- | ---- |\n| `Expires` | Cache expiry date |\n| `Last-Modified` | Cache set date |\n| `X-Request-Fingerprint` | Unique request fingerprint |\n\n\nNote: Caching headers will only be available on single resource requests and their child endpoints. e.g `/anime/1`, `/anime/1/relations`. \nThey won't be available on pages which perform queries, like /anime, or /top/anime, etc.\n\n## Allowed HTTP(s) requests\n\n**Jikan REST API does not provide authenticated requests for MyAnimeList.** This means you can not use it to update your anime/manga list.\nOnly GET requests are supported which return READ-ONLY data.\n\n## HTTP Responses\n\n| HTTP Status | Remarks |\n| ---- | ---- |\n| `200 - OK` | The request was successful |\n| `304 - Not Modified` | You have the latest data (Cache Validation response) |\n| `400 - Bad Request` | You've made an invalid request. Recheck documentation |\n| `404 - Not Found` | The resource was not found or MyAnimeList responded with a `404` |\n| `405 - Method Not Allowed` | Requested Method is not supported for resource. Only `GET` requests are allowed |\n| `429 - Too Many Request` | You are being rate limited by Jikan or MyAnimeList is rate-limiting our servers (specified in the error response) |\n| `500 - Internal Server Error` | Something is not working on our end. If you see an error response with a `report_url` URL, please click on it to open an auto-generated GitHub issue |\n| `503 - Service Unavailable` | The service has broke. |\n\n\n## JSON Error Response\n\n```json\n {\n \"status\": 404,\n \"type\": \"BadResponseException\",\n \"message\": \"Resource does not exist\",\n \"error\": \"Something Happened\",\n \"report_url\": \"https://github.com...\"\n }\n```\n\n| Property | Remarks |\n| ---- | ---- |\n| `status` | Returned HTTP Status Code |\n| `type` | Thrown Exception |\n| `message` | Human-readable error message |\n| `error` | Error response and trace from the API |\n| `report_url` | Clicking this would redirect you to a generated GitHub issue. ℹ It's only returned on a parser error. |\n\n\n## Cache Validation\n\n- All requests return a `ETag` header which is an MD5 hash of the response\n- You can use this hash to verify if there's new or updated content by suppliying it as the value for the `If-None-Match` in your next request header\n- You will get a HTTP `304 - Not Modified` response if the content has not changed\n- If the content has changed, you'll get a HTTP `200 - OK` response with the updated JSON response\n\n![Cache Validation](https://i.imgur.com/925ozVn.png 'Cache Validation')\n\n## Disclaimer\n\n- Jikan is not affiliated with MyAnimeList.net.\n- Jikan is a free, open-source API. Please use it responsibly.\n\n----\n\nBy using the API, you are agreeing to Jikan's [terms of use](https://jikan.moe/terms) policy.\n\n[v3 Documentation](https://jikan.docs.apiary.io/) - [Wrappers/SDKs](https://github.com/jikan-me/jikan#wrappers) - [Report an issue](https://github.com/jikan-me/jikan-rest/issues/new) - [Host your own server](https://github.com/jikan-me/jikan-rest)",
"description": "[Jikan](https://jikan.moe) is an **Unofficial** MyAnimeList API.\nIt scrapes the website to satisfy the need for a complete API - which MyAnimeList lacks.\n\n# Information\n\n⚡ Jikan is powered by it's awesome backers - 🙏 [Become a backer](https://www.patreon.com/jikan)\n\n## Rate Limiting\n\n| Duration | Requests |\n|----|----|\n| Daily | **Unlimited** |\n| Per Minute | 60 requests |\n| Per Second | 3 requests |\n\nNote: It's still possible to get rate limited from MyAnimeList.net instead.\n\n\n## JSON Notes\n- Any property (except arrays or objects) whose value does not exist or is undetermined, will be `null`.\n- Any array or object property whose value does not exist or is undetermined, will be empty.\n- Any `score` property whose value does not exist or is undetermined, will be `0`.\n- All dates and timestamps are returned in [ISO8601](https://en.wikipedia.org/wiki/ISO_8601) format and in UTC timezone\n\n## Caching\nBy **CACHING**, we refer to the data parsed from MyAnimeList which is stored temporarily on our servers to provide better API performance.\n\nAll requests are cached for **24 hours**.\n\nThe following response headers will detail cache information.\n\n| Header | Remarks |\n| ---- | ---- |\n| `Expires` | Cache expiry date |\n| `Last-Modified` | Cache set date |\n| `X-Request-Fingerprint` | Unique request fingerprint (only for cachable requests, not queries) |\n\n\nNote: `X-Request-Fingerprint` will only be available on single resource requests and their child endpoints. e.g `/anime/1`, `/anime/1/relations`.\nThey won't be available on pages which perform queries, like /anime, or /top/anime, etc.\n\n## Allowed HTTP(s) requests\n\n**Jikan REST API does not provide authenticated requests for MyAnimeList.** This means you can not use it to update your anime/manga list.\nOnly GET requests are supported which return READ-ONLY data.\n\n## HTTP Responses\n\nAll error responses are accompanied by a JSON Error response.\n\n| Exception | HTTP Status | Remarks |\n| ---- | ---- | ---- |\n| N/A | `200 - OK` | The request was successful |\n| N/A | `304 - Not Modified` | You have the latest data (Cache Validation response) |\n| `BadRequestException|ValidationException` | `400 - Bad Request` | You've made an invalid request. Recheck documentation |\n| `BadResponseException` | `404 - Not Found` | The resource was not found or MyAnimeList responded with a `404` |\n| `BadRequestException` | `405 - Method Not Allowed` | Requested Method is not supported for resource. Only `GET` requests are allowed |\n| `RateLimitException` | `429 - Too Many Request` | You are being rate limited by Jikan or MyAnimeList is rate-limiting our servers (specified in the error response) |\n| `UpstreamException|ParserException`, Multiple | `500 - Internal Server Error` | Something didn't work. Try again later. If you see an error response with a `report_url` URL, please click on it to open an auto-generated GitHub issue |\n\n## JSON Error Response\n\n```json\n {\n \"status\": 500,\n \"type\": \"InternalException\",\n \"message\": \"Exception Message\",\n \"error\": \"Exception Trace\",\n \"report_url\": \"https://github.com...\"\n }\n```\n\n| Property | Remarks |\n| ---- | ---- |\n| `status` | Returned HTTP Status Code |\n| `type` | Thrown Exception |\n| `message` | Human-readable error message |\n| `error` | Error response and trace from the API |\n| `report_url` | Clicking this would redirect you to a generated GitHub issue |\n\n\n## Cache Validation\n\n- All requests return a `ETag` header which is an MD5 hash of the response\n- You can use this hash to verify if there's new or updated content by suppliying it as the value for the `If-None-Match` in your next request header\n- You will get a HTTP `304 - Not Modified` response if the content has not changed\n- If the content has changed, you'll get a HTTP `200 - OK` response with the updated JSON response\n\n![Cache Validation](https://i.imgur.com/925ozVn.png 'Cache Validation')\n\n## Disclaimer\n\n- Jikan is not affiliated with MyAnimeList.net.\n- Jikan is a free, open-source API. Please use it responsibly.\n\n----\n\nBy using the API, you are agreeing to Jikan's [terms of use](https://jikan.moe/terms) policy.\n\n[v3 Documentation](https://jikan.docs.apiary.io/) - [Wrappers/SDKs](https://github.com/jikan-me/jikan#wrappers) - [Report an issue](https://github.com/jikan-me/jikan-rest/issues/new) - [Host your own server](https://github.com/jikan-me/jikan-rest)",
"termsOfService": "https://jikan.moe/terms",
"contact": {
"name": "API Support (Discord)",
Expand Down Expand Up @@ -4217,8 +4217,6 @@
"enum": [
"mal_id",
"title",
"type",
"rating",
"start_date",
"end_date",
"episodes",
Expand Down