Understanding Magento 2's webapi exception handling

August 28, 2019

Lately I've been working on a few customisations to Magento 2 by introducing new API endpoints using the webapi functionality. A disucssion at work was then sparked regarding how Magento actually handles different response codes in the webapi. How can I trigger a 400, 401, 500 for exmaple? So, I dug into it to find out more.

TL;DR; It turns out, it all depends on the type of Exception that your code throws.

Before I dive into exactly what Exceptions do what, let's quickly dive into where this logic is, and how I found it.

To track this down, I already knew that all api calls go via /rest/[your-endpoint], so this means there is a Controller! That controller is here: https://github.com/magento/magento2/blob/2.3-develop/app/code/Magento/Webapi/Controller/Rest.php

Inside of the dispatch method you'll see this try/catch block:

try {
    $processor = $this->requestProcessorPool->getProcessor($this->_request);
    $processor->process($this->_request);
} catch (\Exception $e) {
    $maskedException = $this->_errorProcessor->maskException($e);
    $this->_response->setException($maskedException);
}

The key line here, is the two lines in the catch statement. It's the $maskedException that has handled all the logic behind what will be returned on the response in terms of status code, and messages to the user.

Now let's dive into the error processor. This can be found here: https://github.com/magento/magento2/blob/2.3-develop/lib/internal/Magento/Framework/Webapi/ErrorProcessor.php

The maskException method contains a lot of logic to figure out what status codes to use, and wether or not to hide the original exception from the end user.

Esentially it boils down to this:

  • If it's an instance of Magento\Framework\Webapi\Exception (aliased as WebapiException) return that. This Exception class requires you to define a status code to be returned, along with other parameters.
  • Instances of Magento\Framework\Exception\LocalizedException are handled slightly differently.
  • NoSuchEntityException will return a 404 (doesn't exist)
  • AuthorizationException or AuthenticationException will return 401
  • Any other instance of a LocalizedException will be a 400.
  • Any other exception will be masked, and hidden from the end user.

With this information, you can see we have a fair amount of flexability. For example, if the error codes returned by an instance of a LocalizedException doesn't suit your requirements, then you just need throw a Magento\Framework\Webapi\Exception with the desired response code that you require.

👌