-
Notifications
You must be signed in to change notification settings - Fork 107
Description
There's a scenario where content negotiation passes, a JSON API exception is thrown, but then this does not get rendered as JSON API.
To reproduce:
- Fire an request within invalid query params with a header of:
Accept: */* - A JSON API exception is thrown (specifically our validation exception).
- Result: you get a
500response.
Expected result is you get a 400 response. See #328 as an example.
The problem here is the exception handler's isJsonApi method does not return true because the client has not specifically asked for JSON API, even though a codec has been matched. So the exception gets given to the normal Laravel render method, which will always render a JSON API exception as a 500 because it does not understand that it has a HTTP status code.
We therefore need to handle these scenarios:
- An exception where a codec has been matched, and that codec can encode. This is easy, you just encode it with the matched codec.
- An exception where a codec has been matched, but it cannot encode. This needs to be passed to the normal Laravel rendering.
- An exception where a codec has not been matched, but the client wants JSON API content - this should just be rendered as JSON API and is effectively the current behaviour.
- An exception where a codec has not been matched, and the client does not want JSON API content. This is the current behaviour of allowing it to be passed to the normal Laravel rendering.
However, if the exception is specifically a JSON API exception and it is going to be passed for normal Laravel rendering, we need to convert it to a HTTP exception before allowing it to pass to the normal rendering - so that the HTTP status code of the JSON API exception is actually respected.