Laravel $request->expectsJson()
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
Title: Understanding and Customizing Laravel's $request->expectsJson() Behavior
Body:
You are doing an Ajax login for your Laravel application with Angular, and you want to trigger a JSON response when the request has an expected JSON format instead of redirecting. This process involves understanding the behavior of Laravel's $request->expectsJson() method and how it interacts with headers like 'Content-Type' and 'X-Requested-With'.
Firstly, let's examine the code you provided:
$http({
method: 'POST',
url: '/admin/login',
headers: {
'Content-Type': 'application/json'
},
data: {email:$scope.email,password:$scope.password}
})
You have set the content type to JSON and are sending JSON as part of your data. This should work according to the $request->expectsJson() method in Laravel. However, you still experience a redirect response instead because Laravel's response is based on certain conditions.
Let's analyze the code at https://github.com/laravel/framework/blob/5.3/src/Illuminate/Http/Request.php#L704:
public function expectsJson()
{
return ($this->ajax() && ! $this->pjax()) || $this->wantsJson();
}
The method returns true if either of these conditions are met:
1. The request is an AJAX (`$request->ajax()`) and not a PJAX (`!$request->pjax()`) request, and the JSON flag is enabled (`$request->wantsJson()`).
2. The JSON flag is explicitly set to true ('WANTS_JSON' or 'X-Requested-With: XMLHttpRequest').
The first condition seems reasonable for ensuring only AJAX requests with expected JSON content should trigger a JSON response. However, the second condition can lead to confusion because it depends on a custom header that is not always present but is still considered in determining if the request expects JSON.
To address this issue and make your Laravel application respond correctly, you could consider adding the 'X-Requested-With: XMLHttpRequest' header explicitly or use a middleware to check for it. Here's an example of how you could do so:
public function handle(Request $request, Closure $next) {
if ($request->has('_token') && ('X-Requested-With' === $request->server->get('HTTP_X_REQUESTED_WITH') || 'XMLHttpRequest' === $request->header('X-Requested-With'))
&& $request->expectsJson()) {
return redirect()->back()
->withInput($request->only($this->username(), 'remember'))
->withErrors($errors);
}
return $next($request);
}
In this middleware, the conditions check for both an AJAX request and a JSON flag request with either an explicit header or implicit by checking if the requested header is set. This way, you can ensure that your Laravel application responds correctly based on the expected JSON format and headers.
To summarize, to address this issue in your Laravel application, make sure to add the 'X-Requested-With: XMLHttpRequest' header explicitly or use a middleware to check for it. This will ensure that when an AJAX request with a JSON payload is sent correctly, you get the desired JSON response instead of redirecting.