Skip to content

Commit

Permalink
Merge branch 'ajaxExceptionJson' of https://github.com/laurencei/fram…
Browse files Browse the repository at this point in the history
…ework into laurencei-ajaxExceptionJson
  • Loading branch information
taylorotwell committed Apr 10, 2017
2 parents 97e8854 + bf5d8c4 commit 4fe6091
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 10 deletions.
27 changes: 17 additions & 10 deletions src/Illuminate/Foundation/Exceptions/Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Psr\Log\LoggerInterface;
use Illuminate\Http\Response;
use Illuminate\Routing\Router;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\RedirectResponse;
use Illuminate\Auth\AuthenticationException;
Expand Down Expand Up @@ -139,7 +140,7 @@ public function render($request, Exception $e)
return $this->convertValidationExceptionToResponse($e, $request);
}

return $request->expectsJson() && config('app.debug')
return $request->expectsJson()
? $this->prepareJsonResponse($request, $e)
: $this->prepareResponse($request, $e);
}
Expand Down Expand Up @@ -212,22 +213,28 @@ protected function prepareResponse($request, Exception $e)
*
* @param \Illuminate\Http\Request $request
* @param \Exception $e
* @return \Symfony\Component\HttpFoundation\Response
* @return \Illuminate\Http\JsonResponse
*/
protected function prepareJsonResponse($request, Exception $e)
{
$status = $this->isHttpException($e) ? $e->getStatusCode() : 500;

$headers = $this->isHttpException($e) ? $e->getHeaders() : [];

return response(json_encode([
'message' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'trace' => $e->getTrace(),
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES), $status, array_merge($headers, [
'Content-Type' => 'application/json',
]));
if (config('app.debug')) {
$response = [
'message' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'trace' => $e->getTrace(),
];
} else {
$response = [
'message' => $this->isHttpException($e) ? $e->getMessage() : 'Server Error',
];
}

return new JsonResponse($response, $status, $headers, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
}

/**
Expand Down
107 changes: 107 additions & 0 deletions tests/Foundation/FoundationExceptionsHandlerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?php

namespace Illuminate\Tests\Foundation;

use Exception;
use Mockery as m;
use PHPUnit\Framework\TestCase;
use Illuminate\Container\Container;
use Illuminate\Config\Repository as Config;
use Illuminate\Foundation\Exceptions\Handler;
use Symfony\Component\HttpKernel\Exception\HttpException;

class FoundationExceptionsHandlerTest extends TestCase
{
protected $config;

protected $container;

protected $handler;

protected $request;

public function setUp()
{
$this->config = m::mock(Config::class);

$this->request = m::mock('StdClass');

$this->container = Container::setInstance(new Container);

$this->container->singleton('config', function () {
return $this->config;
});

$this->container->singleton('Illuminate\Contracts\Routing\ResponseFactory', function () {
return new \Illuminate\Routing\ResponseFactory(
m::mock(\Illuminate\Contracts\View\Factory::class),
m::mock(\Illuminate\Routing\Redirector::class)
);
});

$this->handler = new Handler($this->container);
}

public function tearDown()
{
m::close();
}

public function testReturnsHtmlPageWithStackTraceWhenHtmlRequestAndDebugTrue()
{
$this->config->shouldReceive('get')->with('app.debug', null)->twice()->andReturn(true);
$this->request->shouldReceive('expectsJson')->once()->andReturn(false);

$response = $this->handler->render($this->request, new Exception('My custom error message'))->getContent();

$this->assertContains('<!DOCTYPE html>', $response);
$this->assertContains('<h1>Whoops, looks like something went wrong.</h1>', $response);
$this->assertContains('My custom error message', $response);
$this->assertContains('::main()', $response);
$this->assertNotContains('"message":', $response);
}

public function testReturnsJsonWithStackTraceWhenAjaxRequestAndDebugTrue()
{
$this->config->shouldReceive('get')->with('app.debug', null)->once()->andReturn(true);
$this->request->shouldReceive('expectsJson')->once()->andReturn(true);

$response = $this->handler->render($this->request, new Exception('My custom error message'))->getContent();

$this->assertNotContains('<!DOCTYPE html>', $response);
$this->assertContains('"message": "My custom error message"', $response);
$this->assertContains('"file":', $response);
$this->assertContains('"line":', $response);
$this->assertContains('"trace":', $response);
}

public function testReturnsJsonWithoutStackTraceWhenAjaxRequestAndDebugFalseAndExceptionMessageIsMasked()
{
$this->config->shouldReceive('get')->with('app.debug', null)->once()->andReturn(false);
$this->request->shouldReceive('expectsJson')->once()->andReturn(true);

$response = $this->handler->render($this->request, new Exception('This error message should not be visible'))->getContent();

$this->assertContains('"message": "Server Error"', $response);
$this->assertNotContains('<!DOCTYPE html>', $response);
$this->assertNotContains('This error message should not be visible', $response);
$this->assertNotContains('"file":', $response);
$this->assertNotContains('"line":', $response);
$this->assertNotContains('"trace":', $response);
}

public function testReturnsJsonWithoutStackTraceWhenAjaxRequestAndDebugFalseAndHttpExceptionErrorIsShown()
{
$this->config->shouldReceive('get')->with('app.debug', null)->once()->andReturn(false);
$this->request->shouldReceive('expectsJson')->once()->andReturn(true);

$response = $this->handler->render($this->request, new HttpException(403, 'My custom error message'))->getContent();

$this->assertContains('"message": "My custom error message"', $response);
$this->assertNotContains('<!DOCTYPE html>', $response);
$this->assertNotContains('"message": "Server Error"', $response);
$this->assertNotContains('"file":', $response);
$this->assertNotContains('"line":', $response);
$this->assertNotContains('"trace":', $response);
}
}

0 comments on commit 4fe6091

Please sign in to comment.