Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Cors Laravel Package

spatie/laravel-cors

Adds configurable CORS support to Laravel/Lumen: sets CORS headers on responses, handles preflight requests, and lets you define allowed origins, methods, headers, and credentials via middleware and config. Abandoned since Laravel 7+ has native CORS support.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require spatie/laravel-cors
    

    The package auto-registers its service provider (Spatie\Cors\CorsServiceProvider) and publishes a config file (config/cors.php) via:

    php artisan vendor:publish --provider="Spatie\Cors\CorsServiceProvider"
    
  2. Middleware Registration: Add the Spatie\Cors\Cors middleware to your $middleware array in app/Http/Kernel.php (for global CORS) or to specific routes/middleware groups.

  3. First Use Case: Configure config/cors.php to allow your frontend domain (e.g., paths => ['api/*'], allowed_methods => ['*'], allowed_origins => ['http://your-frontend.com']). Test with a simple API endpoint (e.g., GET /api/test) and verify CORS headers in browser dev tools (Access-Control-Allow-Origin).


Implementation Patterns

Core Workflows

  1. Global CORS Configuration: Use config/cors.php to define default rules (e.g., allowed origins, methods, headers, credentials). Example:

    'paths' => ['api/*', 'sanctum/csrf-cookie'],
    'allowed_methods' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
    'allowed_origins' => ['https://your-app.com', 'https://staging.your-app.com'],
    'allowed_headers' => ['*'],
    'exposed_headers' => [],
    'max_age' => 0,
    'supports_credentials' => false,
    
  2. Route-Specific Overrides: Dynamically override CORS settings for specific routes using middleware parameters:

    Route::middleware(['cors:http://custom-origin.com'])->group(function () {
        // Routes here use custom origin
    });
    

    Or pass an array of options:

    Route::middleware(['cors:api', 'auth:sanctum'])->get('/protected', function () {
        return response()->json(['data' => 'protected']);
    });
    
  3. Preflight Requests (OPTIONS): The package automatically handles OPTIONS requests for configured paths. Ensure OPTIONS is included in allowed_methods and test with:

    curl -X OPTIONS -H "Origin: http://your-frontend.com" http://your-api.com/api/test
    
  4. Integration with Sanctum/Passport: Combine with spatie/laravel-sanctum or laravel/passport by adding Sanctum’s middleware after CORS:

    $middlewareGroups['api'] = [
        \Spatie\Cors\Cors::class,
        'throttle:api',
        \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
        'auth:sanctum',
    ];
    
  5. Dynamic Origin Handling: Use a closure in allowed_origins to dynamically validate origins (e.g., for multi-tenant apps):

    'allowed_origins' => function ($request) {
        return ['https://' . $request->tenant->domain];
    },
    

Gotchas and Tips

Common Pitfalls

  1. Middleware Order:

    • Place CORS middleware before authentication middleware (e.g., Sanctum/Passport) to avoid preflight failures.
    • Avoid placing it after VerifyCsrfToken if using Sanctum, as CSRF tokens may not be accessible during preflight.
  2. Preflight Failures:

    • If OPTIONS requests return 405 Method Not Allowed, ensure:
      • OPTIONS is in allowed_methods.
      • The route exists (even if empty) for OPTIONS requests. Use:
        Route::options('/api/test', function () {});
        
    • For complex setups, log preflight requests:
      \Log::info('Preflight request', ['method' => $request->method(), 'headers' => $request->header()]);
      
  3. Credentials Flag:

    • If using supports_credentials: true, ensure:
      • Frontend explicitly sets withCredentials.
      • allowed_origins does not use * (must list specific domains).
      • Backend responses include Access-Control-Allow-Credentials: true.
  4. Caching Headers:

    • max_age in seconds controls how long browsers cache preflight responses. Set to 0 for dynamic origins or high values (e.g., 86400) for static setups.
  5. Lumen Specifics:

    • In Lumen, register the middleware in bootstrap/app.php:
      $app->middleware(Spatie\Cors\Cors::class);
      

Debugging Tips

  1. Inspect Headers: Use curl or browser dev tools to verify headers:

    curl -I -H "Origin: http://frontend.com" http://api.com/api/test
    

    Expected headers:

    Access-Control-Allow-Origin: http://frontend.com
    Access-Control-Allow-Methods: GET, POST, OPTIONS
    
  2. Logging: Enable debug logging in config/cors.php:

    'debug' => env('CORS_DEBUG', false),
    

    Logs will appear in storage/logs/laravel.log.

  3. Testing: Use Laravel’s HTTP tests to assert CORS headers:

    $response = $this->get('/api/test');
    $response->assertHeader('Access-Control-Allow-Origin', 'http://frontend.com');
    

Extension Points

  1. Custom Middleware: Extend the base middleware by creating a subclass:

    namespace App\Http\Middleware;
    
    use Spatie\Cors\Cors;
    
    class CustomCors extends Cors
    {
        protected function handle($request, Closure $next)
        {
            // Custom logic (e.g., dynamic origin validation)
            return parent::handle($request, $next);
        }
    }
    

    Register it in Kernel.php.

  2. Event Listeners: Listen to cors.headers event to modify headers dynamically:

    \Event::listen('cors.headers', function ($request, $response) {
        if ($request->user()) {
            $response->headers->set('X-Custom-Header', 'value');
        }
    });
    
  3. Conditional Configuration: Use environment-specific configs (e.g., .env variables) to toggle CORS:

    'allowed_origins' => env('APP_ENV') === 'local'
        ? ['http://localhost:3000', 'http://127.0.0.1:8000']
        : ['https://production.com'],
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport