2

I'm building an api at my company using laravel.

The problem I'm encountering is that if you send an api request without defining the correct header with the request you will get html back if there is a failure e.g. authorization failure or findOrFail() failure.

My thinking is that you never want to return html (even if the user has the wrong header).

I have a couple of solutions. In BeforeMiddleware.php I can manually insert a header into the request such as:

// Check if we are on an api route
$apiRoute   = strncmp($uri, '/api/', 5) == 0;

// Insert the request header to force json response
if ($apiRoute){
    $language = $request->header->add('Accept', 'application/json');
}

The 2nd solutions would be to throw an error if they don't have the correct header.

What would be the best way to enforce a json response, what is a good practice for handling api responses in laravel?

Tom Headifen
  • 1,885
  • 1
  • 18
  • 35
  • 1
    Similar question raised in this question https://stackoverflow.com/questions/36366727/how-do-you-force-a-json-response-on-every-response-in-laravel – Adrian Hernandez-Lopez Apr 05 '18 at 21:46
  • The browser will let you know what they accept in the accept header. If the browser doesn't accept JSON what's the point of giving it JSON? – apokryfos Apr 05 '18 at 21:50
  • Also probably easier to check the api route by doing something like `$apiRoute = $request->segment(1) == 'api';` – Simon R Apr 05 '18 at 21:51
  • @apokryfos Can you elaborate on this? What do you mean by 'The browser will let you know'. Is there a setting I can set in laravel to say that what it accepts? – Tom Headifen Apr 05 '18 at 22:00
  • 1
    The request accepts header is set by the client. You as the server should respect what the client sends. If this is for debugging you can just use something like [postman](https://www.getpostman.com/) and send the headers correctly from within there or implement some unit tests instead. – apokryfos Apr 05 '18 at 22:08
  • If you want to force it to return json you can do this: in Handler.php add this in the render method: if (strpos($prefix, 'api') !== false) { if ($exception instanceof ValidationException) { return response()->json(['success' => false, 'error' => $exception->errors(), 'data' => null], 200); } return response()->json(['success' => false, 'error' => $exception->getMessage(), 'data' => null], 200); } – Indra Apr 05 '18 at 22:28

1 Answers1

0

Once you detected that you are on your api path you are out of the woods and can indeed tackle your problem in the app\Exceptions\Handler.php file like suggested on How do you force a JSON response on every response in Laravel?.

For an open source project I created JSON exception objects by Microsoft format as output, but you can choose the jsonapi format (http://jsonapi.org/examples/#error-objects-basics) as you like: https://github.com/StadGent/laravel_site_opening-hours/blob/develop/app/Exceptions/Handler.php (note that on this implementation it is indeed depending from the headers, but you can use your path detection I think)