Problem/Motivation

Currently Exception responses are handled and created in the RequestHandler class. This is a tight coupling, it is hard to change the request handling for JSON API routes. (Almost) the same code to generate exception responses is in three different places in this class.

Proposed resolution

Use a decoupled solution that uses KernelEvents::EXCEPTION.

Remaining tasks

Discuss the solution direction.
Write tests
Finalize the solution
Consider moving other operations to an event subscriber too, e.g. serialization (follow-up issue).

API changes

Add an event subscriber.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Sutharsan created an issue. See original summary.

Sutharsan’s picture

Attached patch is to illustrate the solution direction I propose. It is not working yet.

e0ipso’s picture

This is fantastic! I like where this is going, we should explore more.

Sutharsan’s picture

Assigned: Unassigned » Sutharsan
Issue summary: View changes
FileSize
1.92 KB
1.92 KB

First working version. Time for writing tests...

Sutharsan’s picture

Status: Active » Needs review
FileSize
7.54 KB

Status: Needs review » Needs work

The last submitted patch, 5: jsonapi-exception-event-2810293-4.patch, failed testing.

The last submitted patch, 5: jsonapi-exception-event-2810293-4.patch, failed testing.

e0ipso’s picture

  1. +++ b/src/EventSubscriber/ExceptionSubscriber.php
    @@ -0,0 +1,102 @@
    +    $headers = $exception->getHeaders() + array('Content-Type' => $this->currentRequest->getMimeType($format));
    

    Please use the shorthand syntax []

  2. +++ b/src/EventSubscriber/ExceptionSubscriber.php
    @@ -0,0 +1,102 @@
    +    return $this->currentRequest->query->get('_format') == 'api_json';
    

    All JSONAPI routes have an option flag called _is_jsonapi that we may want to check as well.

e0ipso’s picture

Also, there are some tests failing (uninitialized container?).

We will also need testing for the new subscriber. We already have test coverage for the exception serialization somewhere else, but we'll need to test the other stuff as well. Hopefully a unit test that checks the expected output for:

  • onException
  • applies
e0ipso’s picture

Title: Use exception event for exception response » [FEATURE] Use exception event for exception response
Sutharsan’s picture

FileSize
3.76 KB

Comments from #8 addressed.

e0ipso’s picture

Thanks @Sutharsan. It seems that the actual patch is missing, there is only the interdiff :-P

Wim Leers’s picture

+1 for the changes to RequestHandler.

-1 for the addition of that new exception event subscriber. \Drupal\serialization\EventSubscriber\DefaultExceptionSubscriber already does that, in a more generic way.

e0ipso’s picture

Taking this into an slightly different direction.

e0ipso’s picture

Status: Needs work » Needs review

  • e0ipso committed 85b8b97 on 8.x-1.x authored by Sutharsan
    Issue #2810293 by Sutharsan, e0ipso: [FEATURE] Use exception event for...
e0ipso’s picture

Fixed and merged. I decided to grant authorship to Sutharsan, because he is awesome and did a great job reporting this and taking it to near completion.

Thanks all!

Wim Leers’s picture

  1. +++ b/src/EventSubscriber/DefaultExceptionSubscriber.php
    @@ -0,0 +1,34 @@
    +class DefaultExceptionSubscriber extends SerializationDefaultExceptionSubscriber {
    

    Why do you need this class?

  2. +++ b/src/EventSubscriber/DefaultExceptionSubscriber.php
    @@ -0,0 +1,34 @@
    +  protected static function getPriority() {
    +    return parent::getPriority() + 25;
    +  }
    

    Why does it need to run so early?

e0ipso’s picture

Thanks for the review Wim. I should've mentioned you in the commit credits as well. Shame on me.

Why do you need this class?

Because the \Drupal\serialization\EventSubscriber\DefaultExceptionSubscriber is opinionated on how I have to normalize my exceptions in the setEventResponse. Serializing an array ['message' => $exception->getMessage()] is not good enough for jsonapi.

I think that core should ship with HttpException normalizers that do the ['message' => $exception->getMessage()], if that is the desired format, in the normalizer instead of the event subscriber.

Why does it need to run so early?

No reason, it needs to take precedence over the parent. Since the parent is at -75 and the grandparent at 0 I thought that -50 could be a sensible number. Do you think it's too early?

Sutharsan’s picture

Assigned: Sutharsan » Unassigned
Wim Leers’s picture

I think that core should ship with HttpException normalizers that do the ['message' => $exception->getMessage()], if that is the desired format, in the normalizer instead of the event subscriber.

That makes sense! Can you open a new issue for that? We still have to clean up the current HTTP exception mess for non-HTML formats. So we might as well fix that at the same time.

Thanks for the clarifications!

e0ipso’s picture

Status: Needs review » Fixed
e0ipso’s picture

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.