3

I have a route in my web.php that returns a view:

Route::get('/', function () {
    return view('welcome');
});

welcome is default Laravel view welcome.blade.php.

I have Middleware called AlwaysReturnJson and it contains:

<?php

namespace App\Http\Middleware;

use Closure;

class AlwaysReturnJson
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {

        $request->headers->set('Accept', 'application/json');
        return $next($request);
    }
}

I set up this middleware in Kernel.php as global middleware:

 protected $middleware = [
        \App\Http\Middleware\AlwaysReturnJson::class
    ];

What I expect is to get plain text/json of welcome file in my browser when I navigate to given route but I always get it as html and it render page properly. I checked it, it applies middleware on every request so that is not a problem. Why is this happening and shouldn't it convert that view to a plain text? Am I doing something wrong?

N. Djokic
  • 898
  • 1
  • 6
  • 19

2 Answers2

4

If you want to set a header for your response you can do this:

namespace App\Http\Middleware;

use Closure;

class AlwaysReturnJson
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $response = $next($request);

        $response->headers->set('Content-Type', 'application/json');

        return $response;
    }
}

If you want to force return valid json content use this middleware instead:

namespace App\Http\Middleware;

use Closure;

class AlwaysReturnJson
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $response = $next($request);

        return response()->json($response->getContent());
    }
}

See Laravel docs about after middleware for more info.

You can alternatively return json response on your controller without any middleware needed:

Route::get('/', function () {
    return response()->json(
        view('welcome')->render()
    );
});
Hafez Divandari
  • 8,381
  • 4
  • 46
  • 63
  • Your answer is basically correct, I will mark it as accepted answer but have you tried example that I tried like this: $request->headers->set('Accept', 'application/json'); ? Does it return always json for you? – N. Djokic Jan 15 '20 at 20:32
  • @N.Djokic my first answer just sets `Content-Type` header (not `Accept`). However I've updated my answer and added a code to force your response to be a valid json. – Hafez Divandari Jan 15 '20 at 21:28
1

You may want to use laravel After middleware (the middleware would perform its task after the request is handled by the application) and then set the content-type of response.

<?php

namespace App\Http\Middleware;

use Closure;

class AfterAlwaysReturnJson
{
    public function handle($request, Closure $next)
    {
        $response = $next($request);

        return $response->header('Content-Type', 'application/json');
    }
}
Foued MOUSSI
  • 4,643
  • 3
  • 19
  • 39