Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Lumen with CORS and OPTIONS requests
<?php namespace App\Providers;
use Illuminate\Support\ServiceProvider;
/**
* If the incoming request is an OPTIONS request
* we will register a handler for the requested route
*/
class CatchAllOptionsRequestsProvider extends ServiceProvider {
public function register()
{
$request = app('request');
if ($request->isMethod('OPTIONS'))
{
app()->options($request->path(), function() { return response('', 200); });
}
}
}
<?php namespace App\Http\Middleware;
class CorsMiddleware {
public function handle($request, \Closure $next)
{
$response = $next($request);
$response->header('Access-Control-Allow-Methods', 'HEAD, GET, POST, PUT, PATCH, DELETE');
$response->header('Access-Control-Allow-Headers', $request->header('Access-Control-Request-Headers'));
$response->header('Access-Control-Allow-Origin', '*');
return $response;
}
}

Register the CatchAllOptionsRequestsProvider service provider in bootstrap/app.php which will check the incoming request and response successfully if it is an OPTIONS request.

Add the CorsMiddleware to the $app->middleware([ array in bootstrap/app.php which will attach the following CORS headers to all responses:

  • allow all headers
  • allow requests from all origins
  • allow all the headers which were provided in the request
@maclonghorn
Copy link

maclonghorn commented Apr 19, 2017

I was still having problems, and found that you have to Enable Headers and CORS in Apache

@fifths
Copy link

fifths commented Apr 28, 2017

Thank you so much.

@porfidev
Copy link

porfidev commented May 12, 2017

@rgehan solutions works perfectly adding a Middleware. Im Working Lumen 5.4 in vhost (custom domain) and consuming via Angular4 (locahost)

===
UPDATE > @rgehan your solution doesn't work on anonymous function - download method

    $app->get('images/covers/{image}', function($image = null){
        $path = storage_path().'/app/covers/';
        if(file_exists($path . $image)){
            return response()->download($path . $image);
        }
    });

@kakoma
Copy link

kakoma commented Jul 7, 2017

Thanks @rgehan. This modification works well

@rodralme
Copy link

rodralme commented Jul 28, 2017

Thanks @rgehan. You save my life.

@lazarohcm
Copy link

lazarohcm commented Aug 15, 2017

Thank you mate!

I had to change my response headers a little to make it works on here. The allowed headers now looks like this
'Access-Control-Allow-Headers' => 'access-control-allow-origin,authorization,content-type'

@vamidi
Copy link

vamidi commented Aug 25, 2017

Thank you so much this really helped me out!
Don't know if anyone had to do the same thing, but I had to do

$app->options('/card', ['middleware' => 'cors', '']);

$app->post('/card', ['middleware' => 'cors', 'uses' => 'CardController@createCard']);

to make it work maybe I missing a step.

@s1728k
Copy link

s1728k commented Aug 30, 2017

hi thanks

It worked for me.

hi vamidi you need to register the middleware in bootstrap/app.php inside the app->middleware.

this is explained in top post.

@s1728k
Copy link

s1728k commented Sep 8, 2017

hi I worked me for get request but for post request it is not working for me.

@s1728k
Copy link

s1728k commented Sep 8, 2017

hi,

if you are using the IIS server by chance you set the HTTP request headers as below

Access-Control-Allow-Origin:*
Access-Control-Allow-Methods: 'HEAD, GET, POST, PUT, PATCH, DELETE'
Access-Control-Allow-Headers: 'Origin, Content-Type, X-Auth-Token';

then everything works fine.

@besabellacyrus
Copy link

besabellacyrus commented Sep 27, 2017

and now POST 404 not found

@bosskmk
Copy link

bosskmk commented Oct 7, 2017

Thank you.

@CarlosZM
Copy link

CarlosZM commented Oct 18, 2017

Thanks @rgehan. You save my life.
@danharper try to update your solution with the @rgehan given

@txan2
Copy link

txan2 commented Oct 27, 2017

Thanks @danharper.

I'm still concerned about the usage of Service Provider, isn't it meant to be used for registering things instead of handling things?

@saijayaprakash
Copy link

saijayaprakash commented Nov 4, 2017

Cors middleware is working but catchalloptionsprovider is not working and throwing the following error..Somebody,
screen shot 2017-11-05 at 12 53 59 am
please help me!!

@ccmelas
Copy link

ccmelas commented Nov 19, 2017

Wow...Finally... Thanks a lot

@nusendra
Copy link

nusendra commented Dec 21, 2017

It works. Thanks
So This is the perfect solution for me

  1. Create CatchAllOptionsRequestsProvider.php to App\Providers folder.
<?php namespace App\Providers;
use Illuminate\Support\ServiceProvider;
/**
 * If the incoming request is an OPTIONS request
 * we will register a handler for the requested route
 */
class CatchAllOptionsRequestsProvider extends ServiceProvider {
  public function register()
  {
    $request = app('request');
    if ($request->isMethod('OPTIONS'))
    {
      app()->options($request->path(), function() { return response('', 200); });
    }
  }
}
  1. Then create CorsMiddleware.php
<?php

namespace App\Http\Middleware;

use Closure;

class CorsMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
		//Intercepts OPTIONS requests
		if($request->isMethod('OPTIONS')) {
			$response = response('', 200);
		} else {
			// Pass the request to the next middleware
			$response = $next($request);
		}

		// Adds headers to the response
		$response->header('Access-Control-Allow-Methods', 'HEAD, GET, POST, PUT, PATCH, DELETE');
		$response->header('Access-Control-Allow-Headers', $request->header('Access-Control-Request-Headers'));
		$response->header('Access-Control-Allow-Origin', '*');

		// Sends it
		return $response;
	}
}
  1. In bootstrap/app.php
    add this
$app->middleware([
   App\Http\Middleware\CorsMiddleware::class
]);

$app->register(App\Providers\CatchAllOptionsRequestsProvider::class);

Thanks to @danharper and @rgehan

@zhacarias
Copy link

zhacarias commented Dec 29, 2017

Thanks a lot mate.. 👍

@lmj0011
Copy link

lmj0011 commented May 5, 2018

thanks @davidnknight @rgehan

You're right, all of this Middleware logic can be placed just in the middleware file and not also in a ServiceProvider.

ref:

https://gist.github.com/danharper/06d2386f0b826b669552#gistcomment-1694593

https://gist.github.com/danharper/06d2386f0b826b669552#gistcomment-2013919

@choyan
Copy link

choyan commented Sep 7, 2019

Thanks for summing it up @nusendra

@nusendra
Copy link

nusendra commented Sep 8, 2019

my pleasure bud @choyan

@yogenmohara
Copy link

yogenmohara commented Feb 3, 2020

Works for me. Many Thanks. :)

@skylineCodes
Copy link

skylineCodes commented Feb 21, 2020

Thanks very much for this

@rulatir
Copy link

rulatir commented Apr 8, 2020

Could you please explain how this solution can possibly be correct? My understanding is that OPTIONS exists in the HTTP standard for a reason. Carelessly stubbing it to a no-op must eventually have Dire Consequences, right?

@seinshah
Copy link

seinshah commented Jun 8, 2020

My solution was creating CorsMiddleware as below:

<?php

/**
 * Location: /app/Http/Middleware
 */
namespace App\Http\Middleware;

use Closure;

class CorsMiddleware
{
	/**
	 * Handle an incoming request.
	 *
	 * @param  \Illuminate\Http\Request  $request
	 * @param  \Closure  $next
	 * @return mixed
	 */
	public function handle($request, Closure $next)
	{
		$headers = [
			'Access-Control-Allow-Origin' => '*',
			'Access-Control-Allow-Methods' => 'POST,GET,PATCH,PUT,DELETE,OPTIONS',
			'Access-Control-Max-Age' => '86400',
                        'Access-Control-Allow-Headers' => 'Content-Type,API-KEY'
                ];

		if ($request->isMethod('OPTIONS')) {
			return response()->json('', 200, $headers);
		}

		$response = $next($request);

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

		return $response;
	}
}

Then register the middleware with a name in bootstrap/app.php as below:

$app->routeMiddleware([
  'cors' => App\Http\Middleware\CorsMiddleware::class
]);

Then wrapping required routes between the defined middleware in routes/web.php as below, and adding an additional rule to handle preflight OPTIONS requests:

$router->group(['middleware' => 'cors'], function () use ($router) {
  //All the routes you want to allow CORS for

  $router->options('/{any:.*}', function (Request $req) {
    return;
  });
});

NOTE
Using Chrome, you can get a more detailed error message than Firefox, which will help you to fix the problem and exactly states why there is no Access-Control-Allow-Origin in the response header. Also, keep in mind that any kind of redirect is not allowed in the preflight request, so make sure you don't have such rule in your .htaccess or any other place.

@JhonLimbong17
Copy link

JhonLimbong17 commented Jun 30, 2020

My solution was creating CorsMiddleware as below:

<?php

/**
 * Location: /app/Http/Middleware
 */
namespace App\Http\Middleware;

use Closure;

class CorsMiddleware
{
	/**
	 * Handle an incoming request.
	 *
	 * @param  \Illuminate\Http\Request  $request
	 * @param  \Closure  $next
	 * @return mixed
	 */
	public function handle($request, Closure $next)
	{
		$headers = [
			'Access-Control-Allow-Origin' => '*',
			'Access-Control-Allow-Methods' => 'POST,GET,PATCH,PUT,DELETE,OPTIONS',
			'Access-Control-Max-Age' => '86400',
                        'Access-Control-Allow-Headers' => 'Content-Type,API-KEY'
                ];

		if ($request->isMethod('OPTIONS')) {
			return response()->json('', 200, $headers);
		}

		$response = $next($request);

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

		return $response;
	}
}

Then register the middleware with a name in bootstrap/app.php as below:

$app->routeMiddleware([
  'cors' => App\Http\Middleware\CorsMiddleware::class
]);

Then wrapping required routes between the defined middleware in routes/web.php as below, and adding an additional rule to handle preflight OPTIONS requests:

$router->group(['middleware' => 'cors'], function () use ($router) {
  //All the routes you want to allow CORS for

  $router->options('/{any:.*}', function (Request $req) {
    return;
  });
});

NOTE
Using Chrome, you can get a more detailed error message than Firefox, which will help you to fix the problem and exactly states why there is no Access-Control-Allow-Origin in the response header. Also, keep in mind that any kind of redirect is not allowed in the preflight request, so make sure you don't have such rule in your .htaccess or any other place.

I've tried all of the code, and LOL, no one work for me.
image

I'm still got this error

@saydin
Copy link

saydin commented Aug 11, 2021

Ekran Alıntısı

@saydin
Copy link

saydin commented Aug 11, 2021

hello everyone. I have cors middleware in my lumen as above. cors midlleware works normally when i make a request to lumen from my app. however, whenever a function that I need to send mail runs, I get the error "Call to a member function header() on null".

@rvalitov
Copy link

rvalitov commented Oct 8, 2021

A single file solution with CorsMiddleware.php worked like a charm with Lumen 8.x. The only issue I had that my .htaccess file was not default and was adjusted with the following command:

RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]

In my case I had to remove these lines to make things work.

@saydin
Copy link

saydin commented Oct 8, 2021

Hello everyone again. I solved my error related to this issue. I share my answer with you below.

image
Due to the middleware structure, it returns and switches to the next request after processing. If an error is encountered after the request middleware has passed and did not return, the return value will be null.

For example, after I pass the request from the cors middleware, I am sending a mail via a event as a result of a series of operations. However, even though I changed the mail blade I sent, the cors middleware response value returns null because the php document created in ~/storage/framework/views does not update, and an error occurs.

https://stackoverflow.com/questions/68739232/call-to-a-member-function-header-on-null-in-cors-middleware-in-lumen/68760328#68760328

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment