6

So I store images inside my public folder inside a subdirectory called 'images', and I'm trying to make a request to one of them.

However, I constantly get the error;

Access to fetch at 'http://project.test/images/4obrUhRprw6CXSHsHEGEf4Gje2baKoiS7PQJvS4F.jpeg' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

I think this is because I'm using VueJS as an SPA frontend, as if I head to project.test and make the request it works fine.

I'm using laravel-cors but after some research, I've found that apparently doesn't apply to the public folder, so I've tried playing around with the .htaccess file inside of public and this is what I've got;

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews -Indexes
    </IfModule>

    <IfModule mod_headers.c>
        SetEnvIf Origin "http(s)?://([^.]+\.)?(localhost:8080)$" AccessControlAllowOrigin=$0$1
        Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
        Header set Access-Control-Allow-Credentials true
    </IfModule>


    RewriteEngine On

    # Handle Authorization Header
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

    # Redirect Trailing Slashes If Not A Folder...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} (.+)/$
    RewriteRule ^ %1 [L,R=301]

    # Handle Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]
</IfModule>

However, it still doesn't appear to work and I get the same error when making a request from my Vue localhost instead of project.test. I should also note I'm using Valet.

Hopefully someone can give some help on this.

Borassign
  • 621
  • 2
  • 7
  • 16

5 Answers5

3

I put this line in .htaccess file:

Header always set Access-Control-Allow-Origin "*"

and it worked for me.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
3

I had a similiar problem with following setup:

  • An enabled CorsMiddleware that worked as it is supposed to do with the different get, post, put etc. routes.

  • An images folder inside the "public"-folder of the lumen project. Accessing files inside the images folder would lead to an CORS error, although CorsMiddleware worked for routes.

Solution that worked for me: Based on the suggestion of @Hadeel Mostafa, I added a .htaccess file to the public/images folder with the following line:

Header always set Access-Control-Allow-Origin "*"

Adding the same line to the .htaccess of the public folder on the other hand didn't work. It caused the allow-origin header to be set twice (by CorsMiddleware and .htaccess). So the key in my case, was adding an own .htaccess to the subfolder.

iwan_gu
  • 43
  • 3
  • 1
    Seriously....thank you so much for this answer. I spent hours working on this and this was the only way that I could get CORS images to load while using fruitcake-cors. – Sleewok Jul 11 '22 at 20:06
  • be aware for allowing all traffic has enabled cors – Erlang Parasu Dec 03 '22 at 01:33
1

Add middleware with CORS

<?php
namespace App\Http\Middleware;

use Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode as Middleware;
use Closure;
use Illuminate\Support\Facades\Response;

class CORS extends Middleware {

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {            
        $origin = $request->header('origin');
        $origin = $origin ?? '*';

        // ALLOW OPTIONS METHOD
        $headers = [
            'Access-Control-Allow-Origin' => $origin,
            'Access-Control-Allow-Methods'=> 'GET, POST, DELETE, PUT, OPTIONS, HEAD, PATCH',
            'Access-Control-Allow-Headers'=> 'Authorization,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Set-Cookie',
            'Access-Control-Allow-Credentials'=> 'true'
        ];

        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;
    }

}

File app/Http/Kernel.php

protected $middleware = [
        // Your middleware...

        \App\Http\Middleware\CORS::class,        
    ];
Nick
  • 536
  • 2
  • 8
  • 2
    I'm already using the package laravel-cors which basically does this. According to some research I did the public folder is not affected by middleware. – Borassign Oct 24 '19 at 08:24
1

An easier solution would be to use fruitcake/laravel-cors and edit this line in your cors.php config file:

    'paths' => ['api/*', 'sanctum/csrf-cookie'],

to

    'paths' => ['api/*', 'sanctum/csrf-cookie', '/images/*'],

Happy coding!

Stan Smulders
  • 6,079
  • 1
  • 27
  • 23
1

Add these lines at the top of bootstrap\app.php file. Actually, Middlewares only work with routes not in all requests so to allow it for all add code in where the app is bootstraped.

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: *');
header('Access-Control-Allow-Headers: *');

for testing must refresh browser cache or go to incognito mode because browsers get response from the cache.