Problem/Motivation
Exception handling of HttpExceptions does not pass on headers in the responses it creates. For example, you could throw a MethodNotAllowedHttpException
which adds an Allow
header, however this won't be passed on because we currently only do something like:
$response = new JsonResponse(['message' => $event->getException()->getMessage()], $exception->getStatusCode());
So 405 responses would be missing that header. Same goes for any HttpExceptionInterface
exception which is adding headers. HttpException
itself allows arbitrary headers to be set.
Proposed resolution
Pass on the headers from HttpExceptions to the response, like:
$response = new JsonResponse(['message' => $event->getException()->getMessage()], $exception->getStatusCode(), $execption->getHeaders());
Remaining tasks
This needs some test coverage. Speaking to WimLeers, EntityResourceTestBase
is a good place to add some assertions for this as it already tests 405 responses, but only the body, not the headers. We could alternatively just test this in a generic way in DefaultExceptionSubscriberTest
maybe
User interface changes
N/A
API changes
Correct headers will be added to some responses. More of an addition I guess :)
Data model changes
N/A
Comment | File | Size | Author |
---|---|---|---|
#15 | interdiff-2838949-15.txt | 906 bytes | damiankloip |
#15 | 2838949-15.patch | 9.5 KB | damiankloip |
#13 | interdiff-2838949-13.txt | 2.06 KB | damiankloip |
#13 | 2838949-13.patch | 9.54 KB | damiankloip |
#10 | interdiff-2838949-10-with-fixes.txt | 2.14 KB | damiankloip |
Comments
Comment #2
damiankloip CreditAttribution: damiankloip at Acquia commentedCurrently blocking this on #2739617: Make it easier to write on4xx() exception subscribers
Comment #3
Wim LeersConfirming!
I think we should test this both in
EntityResourceTestBase
(integration test) and inDefaultExceptionSubscriberTest
(unit test).Comment #4
damiankloip CreditAttribution: damiankloip at Acquia commentedLooks like we also will need to fix
DefaultExceptionSubscriberTest
here too, it currently makes little sense :) :But the first parameter is a list of ALLOWED METHODS... Plus not sure HTTP method not allowed == content type not allowed. We should change this to
NotAcceptableHttpException
.Comment #5
Wim LeersHah! :D
Comment #6
damiankloip CreditAttribution: damiankloip at Acquia commentedHere are some fixes for the DefaultExceptionSubscriberTest. This subscriber is not actually the problem. This correctly sets headers see onException and other methods. We will actually need a new unit test for the ExceptionJsonSubscriber class.
Comment #7
damiankloip CreditAttribution: damiankloip at Acquia commentedJust for background, test was originally added in #2594777-12: Accessing a non existing format results in a 500
Comment #8
damiankloip CreditAttribution: damiankloip at Acquia commentedUnblocked!
Comment #9
damiankloip CreditAttribution: damiankloip at Acquia commentedComment #10
damiankloip CreditAttribution: damiankloip at Acquia commentedOK, here is a patch with tests and fixes. When looking at this, I also realised it is not just \Drupal\Core\EventSubscriber\DefaultExceptionSubscriber that had this problem but also Drupal\serialization\EventSubscriber\DefaultExceptionSubscriber.
I also found another bug with the latter from the added test coverage, the response content type is never set, if we know the format and can respond to it, we should set it.
Comment #11
Wim LeersThis part is clear, and is unquestionably a bugfix.
But is this part really necessary?
\Symfony\Component\HttpFoundation\Response::prepare()
sets it automatically:But I guess it's better to be specific. Because that means we can actually ensure (and test) the correct behavior ourselves, rather than relying on Symfony magic.
Which means we're also protected against upstream changes.
Comment #12
Wim LeersOh wait!
This should still update
EntityResourceTestBase
! Every place where a 405 response is being asserted, we should add an assertion for the presence of theAllow
header with the correct header value. Easy peasy :)Comment #13
damiankloip CreditAttribution: damiankloip at Acquia commentedThat's a good point! It's easy enough for us to add some new assertions in there for that!
Comment #15
damiankloip CreditAttribution: damiankloip at Acquia commentedOver zealous removal of
_format
from the Request path in the test.Comment #16
Wim LeersPerfect! :)
Comment #17
Wim LeersClarifying title. Which then also explains why this should be a top priority.
Comment #18
Wim LeersComment #19
alexpottCommitted 98e7ac3 and pushed to 8.3.x. Thanks!