lararara's avatar

CORS Error with Cloudflare R2 Private Bucket, Filament Spatie Media Upload Plugin

I cannot upload images in Filament with Filament Spatie Media Upload Plugin, it's always giving me a 403 CORS Missing Allow Origin.

This is the plugin, https://filamentphp.com/plugins/filament-spatie-media-library, and the only thing it mentions for using private uploads is setting the visibility to private.

I can confirm this isn't an issue with setting up R2 on my Laravel project, following, https://www.luckymedia.dev/blog/integrating-cloudflare-r2-storage-with-laravel. Nor is it an issue with Spatie Media LIbrary, as I can run that in PHP Artisan Tinker and it'd be uploaded.

// Put example file into r2, the default, storage. Works fine
Storage::disk()->put('test.txt', 'test');

// Add url image to model and test spatie media library upload
// Works all fine
$url = 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/27/PHP-logo.svg/711px-PHP-logo.svg.png';

$model = new BasicModel([
    'name' => 'coolImage',
    'icon' => $url,
    'user_id' => '0195ef2e-uuid-here'
]);
try {
    $model->addMediaFromUrl($url)->toMediaCollection();
} catch (Exception $e) {
    Log::error($e->getMessage());
}

$model->save();

With the relevant .env values

FILESYSTEM_DISK=r2
MEDIA_DISK=r2
FILAMENT_FILESYSTEM_DISK=r2

R2_ACCESS_KEY_ID=123
R2_SECRET_ACCESS_KEY=123
R2_BUCKET=test-cf-bucket
R2_ENDPOINT=https://123.r2.cloudflarestorage.com

config/filesystems

        'r2' => [
            'driver' => 's3',
            'key' => env('R2_ACCESS_KEY_ID'),
            'secret' => env('R2_SECRET_ACCESS_KEY'),
            'region' => 'auto',
            'bucket' => env('R2_BUCKET'),
            'url' => env('R2_URL'),
            'endpoint' => env('R2_ENDPOINT'),
            'use_path_style_endpoint' => env('R2_USE_PATH_STYLE_ENDPOINT', false),
            'throw' => false,
        ],

My Form is not using any crazy settings, only the plugin and setting visibility to private.

BasicFormResource.php

                Forms\Components\SpatieMediaLibraryFileUpload::make('image')
                    ->image()
                    ->visibility('private')
                    ->maxFiles(1),

In R2 CORS Settings, I'm using a very open permission to test it works in localhost

[
  {
    "AllowedOrigins": [
      "*"
    ],
    "AllowedMethods": [
      "GET",
      "PUT",
      "POST",
      "DELETE",
      "HEAD"
    ],
    "AllowedHeaders": [],
    "ExposeHeaders": []
  }
]

The XML file from the CORS error says to check my secret access key and signing method,

<Code>SignatureDoesNotMatch</Code>
<Message>
		The request signature we calculated does not match the signature you provided. Check your secret access key and signing method.
</Message>
<CanonicalRequest>
    GET /livewire-tmp/MKLfjkllkjvmetaUEhQLWxvZ28uc3ZnLnBuZw%3D%3D-.png X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=12jkfj12klj18fkls%2F20250403%2Fauto%2Fs3%2Faws4_request&X-Amz-Date=20250101T010111Z&X-Amz-Expires=300&X-Amz-SignedHeaders=host%3Bx-amz-acl&x-amz-acl=private host:test-cf.r2.cloudflarestorage.com x-amz-acl: host;x-amz-acl UNSIGNED-PAYLOAD
</CanonicalRequest>
0 likes
3 replies
lararara's avatar

What am I missing? I don't see anything in the Filament Spatie Media Library Plugin docs that mentions this CORS issue. My R2 settings has set all origins to be allowed.

I haven't published any CORS settings in Laravel, instead keeping them default.

lararara's avatar
lararara
OP
Best Answer
Level 2

So I allowed all headers and then it worked. Here's the final output of my R2 CORS settings incase someone else gets stuck on this. Note the allowed origin should be changed to your prod url after localhost testing is done.

[
  {
    "AllowedOrigins": [
      "http://127.0.0.1:8000"
    ],
    "AllowedMethods": [
      "GET",
      "PUT",
      "POST",
      "DELETE",
      "HEAD"
    ],
    "AllowedHeaders": [
      "*"
    ],
    "ExposeHeaders": []
  }
]
3 likes
sirabdull's avatar

Hello ,i'm facing the same issue currently. my application is multitenant so diffrent users can have diffrent domains , how can i achive this Thank you

Please or to participate in this conversation.