0

I have created a custom REST API plugin for an endpoint. I have set the accepted format to json using the configuration options. This works. However, if we set the content-type to something other than application/json I am getting a 500 error.

I am seeking to know how this exception can be handled more gracefully. However, what is preventing this is the fact that I am not able to get the Request object in the plugin code.

I tried extending the default EventSubscriber services but they do not seem to be of help. I am seeing that this seems to be an open issue in Drupal.org

https://www.drupal.org/project/drupal/issues/2954286

I am thinking of altering the route and set the default format to json as in manually added custom routes but open to better ways.

Any help would be appreciated.

0

For the record, here is how I managed to solve the issue. This is a workaround but it allows for graceful degradation.

  1. I created an event subscriber that extends HttpExceptionSubscriberBase
  2. There is an onException method that retrieves the event that generated the exception
  3. From the event, we can get the request type and handle the exception.
  4. By overriding the method we can handle this exception

class MyClassService extends HttpExceptionSubscriberBase {
public function onException(GetResponseForExceptionEvent $event) {
    $exception = $event->getException();

    // Make the exception available for example when rendering a block.
    $request = $event->getRequest();
    $request->attributes->set('exception', $exception);

    $handled_formats = $this->getHandledFormats();
    $format = $request->query->get(MainContentViewSubscriber::WRAPPER_FORMAT, $request->getRequestFormat());
    if ($exception instanceof HttpExceptionInterface && (empty($handled_formats) || in_array($format, $handled_formats))) {
      $method = 'on' . $exception->getStatusCode();
      // Keep just the leading number of the status code to produce either a
      // on400 or a 500 method callback.
      $method_fallback = 'on' . substr($exception->getStatusCode(), 0, 1) . 'xx';
      // We want to allow the method to be called and still not set a response
      // if it has additional filtering logic to determine when it will apply.
      // It is therefore the method's responsibility to set the response on the
      // event if appropriate.
      if (method_exists($this, $method)) {
        $this->$method($event);
      }
      elseif (method_exists($this, $method_fallback)) {
        $this->$method_fallback($event);
      }
    }
    // We are now assuming that this a special RuntimeException
    // where the Content-type header is not set to json or missing.
    if ('json' != $request->getContentType()) {
      if (method_exists($this, 'on415')) {
        $this->on415($event);
      }
    }
  }


public function on415(GetResponseForExceptionEvent $event) {
    $method_exception = [];
    $method_exception['message'] = 'Missing or unsupported Content-Type request header.';
    $response = new JsonResponse($method_exception, 415);
    $event->setResponse($response);
}
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.