Laravel 5.1 API Enable Cors

136,400

Solution 1

Here is my CORS middleware:

<?php namespace App\Http\Middleware;

use Closure;

class CORS {

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

        header("Access-Control-Allow-Origin: *");

        // ALLOW OPTIONS METHOD
        $headers = [
            'Access-Control-Allow-Methods'=> 'POST, GET, OPTIONS, PUT, DELETE',
            'Access-Control-Allow-Headers'=> 'Content-Type, X-Auth-Token, Origin'
        ];
        if($request->getMethod() == "OPTIONS") {
            // The client-side application can set only headers allowed in Access-Control-Allow-Headers
            return Response::make('OK', 200, $headers);
        }

        $response = $next($request);
        foreach($headers as $key => $value)
            $response->header($key, $value);
        return $response;
    }

}

To use CORS middleware you have to register it first in your app\Http\Kernel.php file like this:

protected $routeMiddleware = [
        //other middlewares
        'cors' => 'App\Http\Middleware\CORS',
    ];

Then you can use it in your routes

Route::get('example', array('middleware' => 'cors', 'uses' => 'ExampleController@dummy'));
Edit: In Laravel ^8.0 you have to import the namespace of the controller and use the class like this:
use App\Http\Controllers\ExampleController;

Route::get('example', [ExampleController::class, 'dummy'])->middleware('cors');

Solution 2

I always use an easy method. Just add below lines to \public\index.php file. You don't have to use a middleware I think.

header('Access-Control-Allow-Origin: *');  
header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');

Solution 3

I am using Laravel 5.4 and unfortunately although the accepted answer seems fine, for preflighted requests (like PUT and DELETE) which will be preceded by an OPTIONS request, specifying the middleware in the $routeMiddleware array (and using that in the routes definition file) will not work unless you define a route handler for OPTIONS as well. This is because without an OPTIONS route Laravel will internally respond to that method without the CORS headers.

So in short either define the middleware in the $middleware array which runs globally for all requests or if you're doing it in $middlewareGroups or $routeMiddleware then also define a route handler for OPTIONS. This can be done like this:

Route::match(['options', 'put'], '/route', function () {
    // This will work with the middleware shown in the accepted answer
})->middleware('cors');

I also wrote a middleware for the same purpose which looks similar but is larger in size as it tries to be more configurable and handles a bunch of conditions as well:

<?php

namespace App\Http\Middleware;

use Closure;

class Cors
{
    private static $allowedOriginsWhitelist = [
      'http://localhost:8000'
    ];

    // All the headers must be a string

    private static $allowedOrigin = '*';

    private static $allowedMethods = 'OPTIONS, GET, POST, PUT, PATCH, DELETE';

    private static $allowCredentials = 'true';

    private static $allowedHeaders = '';

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
      if (! $this->isCorsRequest($request))
      {
        return $next($request);
      }

      static::$allowedOrigin = $this->resolveAllowedOrigin($request);

      static::$allowedHeaders = $this->resolveAllowedHeaders($request);

      $headers = [
        'Access-Control-Allow-Origin'       => static::$allowedOrigin,
        'Access-Control-Allow-Methods'      => static::$allowedMethods,
        'Access-Control-Allow-Headers'      => static::$allowedHeaders,
        'Access-Control-Allow-Credentials'  => static::$allowCredentials,
      ];

      // For preflighted requests
      if ($request->getMethod() === 'OPTIONS')
      {
        return response('', 200)->withHeaders($headers);
      }

      $response = $next($request)->withHeaders($headers);

      return $response;
    }

    /**
     * Incoming request is a CORS request if the Origin
     * header is set and Origin !== Host
     *
     * @param  \Illuminate\Http\Request  $request
     */
    private function isCorsRequest($request)
    {
      $requestHasOrigin = $request->headers->has('Origin');

      if ($requestHasOrigin)
      {
        $origin = $request->headers->get('Origin');

        $host = $request->getSchemeAndHttpHost();

        if ($origin !== $host)
        {
          return true;
        }
      }

      return false;
    }

    /**
     * Dynamic resolution of allowed origin since we can't
     * pass multiple domains to the header. The appropriate
     * domain is set in the Access-Control-Allow-Origin header
     * only if it is present in the whitelist.
     *
     * @param  \Illuminate\Http\Request  $request
     */
    private function resolveAllowedOrigin($request)
    {
      $allowedOrigin = static::$allowedOrigin;

      // If origin is in our $allowedOriginsWhitelist
      // then we send that in Access-Control-Allow-Origin

      $origin = $request->headers->get('Origin');

      if (in_array($origin, static::$allowedOriginsWhitelist))
      {
        $allowedOrigin = $origin;
      }

      return $allowedOrigin;
    }

    /**
     * Take the incoming client request headers
     * and return. Will be used to pass in Access-Control-Allow-Headers
     *
     * @param  \Illuminate\Http\Request  $request
     */
    private function resolveAllowedHeaders($request)
    {
      $allowedHeaders = $request->headers->get('Access-Control-Request-Headers');

      return $allowedHeaders;
    }
}

Also written a blog post on this.

Solution 4

barryvdh/laravel-cors works perfectly with Laravel 5.1 with just a few key points in enabling it.

  1. After adding it as a composer dependency, make sure you have published the CORS config file and adjusted the CORS headers as you want them. Here is how mine look in app/config/cors.php

    <?php
    
    return [
    
        'supportsCredentials' => true,
        'allowedOrigins' => ['*'],
        'allowedHeaders' => ['*'],
        'allowedMethods' => ['GET', 'POST', 'PUT',  'DELETE'],
        'exposedHeaders' => ['DAV', 'content-length', 'Allow'],
        'maxAge' => 86400,
        'hosts' => [],
    ];
    
  2. After this, there is one more step that's not mentioned in the documentation, you have to add the CORS handler 'Barryvdh\Cors\HandleCors' in the App kernel. I prefer to use it in the global middleware stack. Like this

    /**
     * The application's global HTTP middleware stack.
     *
     * @var array
     */
    protected $middleware = [
        'Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode',
        'Illuminate\Cookie\Middleware\EncryptCookies',
        'Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse',
        'Illuminate\Session\Middleware\StartSession',
        'Illuminate\View\Middleware\ShareErrorsFromSession',
    
        'Barryvdh\Cors\HandleCors',
    
    ];
    

    But its up to you to use it as a route middleware and place on specific routes.

This should make the package work with L5.1

Solution 5

For me i put this codes in public\index.php file. and it worked just fine for all CRUD operations.

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS, post, get');
header("Access-Control-Max-Age", "3600");
header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token');
header("Access-Control-Allow-Credentials", "true");

Share:
136,400

Related videos on Youtube

Leonardo Lobato
Author by

Leonardo Lobato

Updated on November 13, 2021

Comments

  • Leonardo Lobato
    Leonardo Lobato over 2 years

    I've looked for some ways to enable cors on laravel 5.1 specifically, I have found some libs like:

    https://github.com/neomerx/cors-illuminate

    https://github.com/barryvdh/laravel-cors

    but none of them has a implementation tutorial specifically to Laravel 5.1, I tried to config but It doesn't work.

    If someone already implemented CORS on laravel 5.1 I would be grateful for the help...

    • rdiz
      rdiz over 8 years
      Barryvdh's is for Laravel 5, and really it should work out of the box with 5.1 as well. Did you try it?
    • Leonardo Lobato
      Leonardo Lobato over 8 years
      Yes I tried, but I still getting the following message ( it's a angular frontend) XMLHttpRequest cannot load api.address.com. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin '127.0.0.1:8080' is therefore not allowed access. But I have already added the local address on the cors files 'supportsCredentials' => true, 'allowedOrigins' => ['127.0.0.1:8080'], 'allowedHeaders' => ['*'], 'allowedMethods' => ['GET', 'POST', 'PUT', 'DELETE'], 'exposedHeaders' => [], 'maxAge' => 0, 'hosts' => [],
    • rdiz
      rdiz over 8 years
      Which message do you get?
    • Leonardo Lobato
      Leonardo Lobato over 8 years
      XMLHttpRequest cannot load api.address.com. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin '127.0.0.1:8080'; is therefore not allowed access
    • rdiz
      rdiz over 8 years
      Did you publish the config file and edit it accordingly?
    • Kjell
      Kjell over 8 years
      Did you have a look at the response header in your browser? There the Access-Control-Allow-Origin header should be set to the right domain. Also you could try to set it yourself on one route "by hand"...
    • Leonardo Lobato
      Leonardo Lobato over 8 years
      Access-Control-Allow-Credentials → true Access-Control-Allow-Headers → Origin, Content-Type, Accept, Authorization, X-Request-With Access-Control-Allow-Methods → GET, POST, OPTIONS Access-Control-Allow-Origin → * The cors seems to woking, I already tried my localhost instead of * but still don't working
  • suncoastkid
    suncoastkid over 8 years
    Works on Apache but not IIS :(
  • retrograde
    retrograde about 8 years
    Just to clarify - is this an alternative to the packages mentioned in the question?
  • Alex Kyriakidis
    Alex Kyriakidis about 8 years
    @retrograde yeah if you pick this solution you don't have to use a package.
  • Efriandika Pratama
    Efriandika Pratama almost 8 years
    it is not elegant
  • Joel James
    Joel James almost 8 years
    @EfriandikaPratama why not? index.php file is being used on all HTTP requests. So it is an easy and user-friendly way.
  • Efriandika Pratama
    Efriandika Pratama almost 8 years
    It is not elegant. More elegant if you put that code in middleware.
  • Anthony
    Anthony over 7 years
    @EfriandikaPratama saying the same thing over and over doesn't prove your point.
  • Ole K
    Ole K over 7 years
    This is really good solutions, also the OPTIONS method to check if Origin is allowed - like it in the middleware - But for some reason I can not get it all running for POST methods in laravel 5.X - Any ideas?
  • bashleigh
    bashleigh about 7 years
    Did you add a method spoof somewhere? When I call POST/GET I get to this middleware but using method OPTIONS I do not get to this middleware on the same route? Really odd... in the route list there is no OPTIONS method so I'm presuming it's possibly that the method OPTIONS is invalid OR being caught elsewhere. This is laravel 5.4 so could be something that's been added?
  • MM2
    MM2 about 6 years
    it is good if you want to enable CORS for your complete app, but not applicable if you want to enable CORS on certain routes. which I think make more sense to use Middleware instead.
  • arikanmstf
    arikanmstf almost 6 years
    Note that, for me it is version 5.6 , and I also needed to add \App\Http\Middleware\Cors::class at Kernel.php, inside protected $middleware array. If anyone has suffer like me, can try this
  • shashi verma
    shashi verma over 5 years
    @AlexKyriakidis Thanks for the solution, as I am using the laravel5.7 and I have this syntax return $next($request); in my middleware. Should I use this or not?
  • ronaldtgi
    ronaldtgi over 5 years
    This is short and sweet, I think protecting in middleware isn't necessary when all routes are already protected with OAuth or JWT.
  • Chamidu Jayaruwan
    Chamidu Jayaruwan almost 5 years
    This will enable access for the whole site / program, not just APIs.
  • darksoulsong
    darksoulsong almost 5 years
    This is failing on OPTIONS.
  • darksoulsong
    darksoulsong almost 5 years
    Awesome, I read your blog post and it worked like a charm. Thanks!
  • Delmontee
    Delmontee over 4 years
    @arikanmstf you just made my week!! This was the problem I was having with my CORS. You are right, adding it to the protected $middleware in kernel.php fixed it! Many thanks.
  • Arun P
    Arun P over 4 years
    @Rishabh I Was just checking about some CORS related Laravel issues, almost every answer is just the same, but this one is actually very nice ..
  • Ogbonna Vitalis
    Ogbonna Vitalis over 4 years
    Thank you for this. I am tired of installing bunch of packages just to implement a simple feature
  • Maxim Abdalov
    Maxim Abdalov over 4 years
    Just add App\Http\Middleware\CORS::class in protected $middleware, and it will work for any request
  • Bahman.A
    Bahman.A over 4 years
    I have been looking for details on each of the config file's elements especially 'exposedHeaders' and 'supportsCredentials', but unfortunately haven't had any success yet, do you mind to give some details on them or maybe post a reference please? much appreciated!!
  • user931018
    user931018 over 4 years
    THANK YOU! Jeez I've struggled with this for weeks. None of the packages worked for me. This is great!
  • Cleanshooter
    Cleanshooter about 4 years
    This didn't not work for me in Laravel 6.9, this did: github.com/fruitcake/laravel-cors
  • George
    George almost 4 years
    This solution is incomplete. It solved partially the CORS error, it didn't work on some POST requests.
  • mili
    mili almost 4 years
    This is a nice and simple solution, much thanks. But I changed route on my web.php to get it working on Laravel 5.5 Route::get('example', 'ExampleController@dummy')->middleware(CORS::class);
  • Prashant
    Prashant about 3 years
    Worked like a charm for L5.2 for me.. just a quick note, CORS handling is inbuilt with L8 now.. Thanks
  • Bob Arezina
    Bob Arezina almost 3 years
    This is a great solution. It's unfortunate that Laravel doesn't have an inbuilt quick way to turn this off.
  • Bob Arezina
    Bob Arezina almost 3 years
    This solution is generally too complex for those that want their local development environment to just work without the pain of CORS.