Ad

Laravel 5: Routing CORS Issue On Just One URL

- 1 answer

I am trying to make 2 ajax requests to an external laravel site. One of the requests works perfectly ("list"). The other one ("savedevice") gives me the following error:

Access to XMLHttpRequest at 'http://localhost/somesite/devicecreate' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

The origin is null because the request comes from a local html.

I have already created a CORS middleware solution that works for the first route but not the second.

The 2 routes are stored in web.php as follows:

  Route::post('/devicecreate','[email protected]')->middleware('cors');
  Route::post('/list', '[email protected]')->middleware('cors');

Here is my ajax request function in javascript

var ajaxRequest = function ( url, data, callback ) {

        var  xhr = new XMLHttpRequest();

        xhr.onerror = function(e) { 
              console.log("Ajax request error");
        };

        xhr.addEventListener("load",function () {
              xhr.responseJSON = JSON.parse( xhr.responseText );
              callback( xhr.responseJSON);
        });

        xhr.open("POST", url );
        xhr.setRequestHeader("X-Requested-With","XMLHttpRequest");
        xhr.send(data);
};

At the moment (for testing purposes) both route methods do the same thing. But only "/list" works.

If I try php artisan route:list I can see both "devicecreate" and "list" with the same Methods, correct Actions and same Middleware

My CORS middleware looks like this:

<?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)
     {

         if ($request->getMethod() == "OPTIONS") {
             return response(['OK'], 200)
             ->withHeaders([
            'Access-Control-Allow-Origin' => '*',
            'Access-Control-Allow-Methods' => 'GET,POST',
            'Access-Control-Allow-Headers' => 'Authorization,Content-Type,X-Requested-With,XMLHttpRequest',
          ]);
    }

    return $next($request)
    ->header('Access-Control-Allow-Origin', '*')
    ->header('Access-Control-Allow-Methods', 'GET,POST')
    ->header('Access-Control-Allow-Headers','Authorization,Content-Type,X-Requested-With,XMLHttpRequest');

      }
  }

I also tried to run php artisan route:cache.

I have tried renaming the route but it makes no difference.

Can anyone help?

Ad

Answer

24 hours later I have the solution for anybody experiencing any of the following:

  • CORS / cross domain error posting ajax from an external source (preflight of otherwise)
  • 419 Unknown status
  • Issues surrounding CSRF tokens when posting from external sites.

1) create a CORS middleware (https://laravel.com/docs/5.8/middleware). You can use my middleware code displayed above.

2) Make sure you add the middleware to the Http/Kernal.php file under protected $routeMiddleware, for example: 'cors' => \App\Http\Middleware\Cors::class,

3) Attach the middleware only to the routes that need it. In my case this is:

Route::post('/setdevice','[email protected]')->middleware('cors');
Route::post('/list', '[email protected]')->middleware('cors');

4) Remember to exclude your external Ajax requests from the CSRF Token verification! My problem is I had forgotten to add the second route!! So in my case I added these to the protected $except parameter in Http/Middleware/VerifyCsrfToken.php:

 protected $except = [
        'list',
        'savedevice',
    ];
Ad
source: stackoverflow.com
Ad