I recently tries enabling CORS in Laravel 5.4 but unfortunately it doesn't want to work. I have included the code and the error that it's giving me below. Can anyone help finding out why it isn't working? I have passed the required headers.
I have renamed my domain to domain.uk just for example purposes and I don't wan't to expose the domain of my site just yet as its under development.
Routes (Made the one route ::any for testing purposes while developing, usually on production it would be post):
Route::group(['domain' => 'api.domain.uk', 'namespace' => 'Api'], function() {
Route::group(['middleware' => ['cors'], 'prefix' => 'call'], function() {
Route::get('/rooms/{id}/get-locked-status', 'ApiController#getRoomLockStatus');
Route::any('/rooms/{id}/update-locked-status', 'ApiController#updateRoomLockStatus');
});
});
Error:
XMLHttpRequest cannot load http://api.domain.uk/ajax/rooms/1/update-locked-status. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://ice.domain.uk' is therefore not allowed access. The response had HTTP status code 500.
Middleware:
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)
{
return $next($request)
->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
->header('Access-Control-Allow-Headers', 'Content-Type, Accept, Authorization, X-Requested-With, Application');
}
}
Ajax:
function toggleDoors(roomId) {
$.ajax({
url: 'http://api.domain.uk/ajax/rooms/' + roomId + '/update-locked-status',
type: "POST",
success: function(data) {
alert(data);
}
});
}
ApiController:
<?php
namespace App\Http\Controllers\Api;
use Auth;
use App\User;
use App\Http\Controllers\Controller;
use Validator;
use Redirect;
use Illuminate\Http\Request;
use App\Database\Frontend\Other\Rooms;
class ApiController extends Controller
{
public function getRoomLockStatus($id) {
$room = Rooms::find($id);
if ($room == null) {
return response('bad request', 400);
}
else {
return $room->rp_locked;
}
}
public function updateRoomLockStatus(Request $request, $id) {
$room = Rooms::find($id);
if ($room == null) {
return response('bad request', 400);
}
$room->rp_locked = $room->rp_locked == '1' ? '0' : '1';
$room->save();
$responseText = $room->rp_locked == '1' ?
'Your doors have been locked.' : 'Your doors have been unlocked.';
return response($responseText, 200);
}
}
See https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS#Preflighted_requests_in_CORS
If your problem in OPTIONS method.
Kernel::$routeMiddleware not working in Laravel 5.4 for request method OPTIONS, see https://github.com/laravel/framework/blob/v5.4.0/src/Illuminate/Routing/RouteCollection.php#L214.
For use CORS middleware, enable it in Kernel::$middleware array. It is not good, but no other way.
For example, I use next middleware class for SPA and API, attention, it is not middleware 'cors' for routes
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
/**
* OptionsCorsResponse middleware - add CORS headers if request method OPTIONS
*/
class OptionsCorsResponse
{
/**
*
* #param Request $request
* #param Closure $next
* #return Response
*/
public function handle($request, Closure $next)
{
/* #var $response Response */
$response = $next($request);
if (!$request->isMethod('OPTIONS')) {
return $response;
}
$allow = $response->headers->get('Allow'); // true list of allowed methods
if (!$allow) {
return $response;
}
$headers = [
'Access-Control-Allow-Methods' => $allow,
'Access-Control-Max-Age' => 3600,
'Access-Control-Allow-Headers' => 'X-Requested-With, Origin, X-Csrftoken, Content-Type, Accept',
];
return $response->withHeaders($headers);
}
}
and enable it in App\Http\Kernel
protected $middleware = [
// ...
\App\Http\Middleware\OptionsCorsResponse::class,
];
Origin 'http :// ice . domain . uk' is therefore not allowed
access. The response had HTTP status code 500.
Debug your code, because it generate some exception. Use any REST client with OPTIONS method.
In the CORS, browser first send the OPTIONS request to the specified route.
In CORS, a preflight request with the OPTIONS method is sent, so that the server can respond whether it is acceptable to send the request with these parameters:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS
So Change your middleware like this:
public function handle($request, Closure $next)
{
if ($request->isMethod('OPTIONS')){
$response = Response::make();
} else {
$response = $next($request);
}
return $response
->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
->header('Access-Control-Allow-Headers', 'Content-Type, Accept, Authorization, X-Requested-With, Application');
}
If you want to allow other headers to your routes, please add them in the 'Access-Control-Allow-Headers' header field.
You can do it easily by adding headers in bootstrap/app.php
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: *');
header('Access-Control-Allow-Headers: *');
If none of this working, add cors on apache virtual host configuration (If you use virtual host).
Go to /etc/apache2/sites-available and add something like this gist
then sudo a2ensite example.conf and sudo service apache2 reload ;)
I ran into a sudden CORS issue recently that was not caused by CORS header configuration, I discovered the following:
There are Red Herring scenarios that can also cause a CORS Cross Origin error to display and yet not have anything to do with CORS configuration, It is a result of when CORS is handled by middleware and something else prevents it from being triggered.
The following can indirectly cause the error to display in a browser response:
A PHP error in a Middleware class.
return $next($request); not being fired in middleware class method handle.
Route::middleware in web or api router configs reference a middleware that no longer exists or is miss spelt.
Same as above point but middleware specified in a Controller with $this->middleware();
Any of these can prevent a Cors middleware from ever being fired because the app exits too early and never sets the headers and thus results in a CORS error instead of a 500 Server Header error as a result of bad middleware files or bad references to middleware.
If you are certain you have configured CORS correctly then you should
check your PHP error logs for Middleware errors.
I am using Laravel 6 and up. This url helped me in solving my CORS issue: https://medium.com/#petehouston/allow-cors-in-laravel-2b574c51d0c1
Use this code instead of code in the url:
<?php
namespace App\Http\Middleware;
use Closure;
class Cors
{
public function handle($request, Closure $next)
{
return $next($request)
->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
->header('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type,X-Token-Auth, Authorization');
}
}
Also, if you want to use middleware through the entire application then you need to make changes in Kernel.php:
protected $middleware = [
\App\Http\Middleware\Cors::class, //add this line to $middleware variable
]
I had a problem handling files using the withHeaders() method, so thanks to the tips below i came up with this working code:
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if ($request->isMethod('OPTIONS'))
{
return response()->json('{"method":"OPTIONS"}', 200, $headers);
}
$response = $next($request);
$response->headers->set('Access-Control-Expose-Headers', 'Content-Disposition');
$response->headers->set('Access-Control-Allow-Origin', 'http://localhost:8080','http://localhost','https://edu.pilateswien.org');
$response->headers->set('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS');
//return $response->withHeaders($headers);
return $response;
}
Sergei is right, the problem is caused because of the preflight request: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS#Preflighted_requests_in_CORS
Thus adding a middleware only to a group of endpoints won't work, because the preflight is using the OPTION method and not the GET method.
This package solves exactly this issue, by having a middleware that is put in your kernel for all routes, but then you filter the routes where you want to allow CORS in config/cors.php.
Thus you can also handle the preflight request that come with the option method.
In short, install the package:
composer require fruitcake/laravel-cors
put the middleware in your middleware array:
protected $middleware = [
\Fruitcake\Cors\HandleCors::class,
// ...
];
publish the config file:
php artisan vendor:publish --tag="cors"
And specify in paths inside config/cors which routes (or only a single route) you want to allow:
'paths' => ['api/*'],
See also this blog post for more.
Just add this code on your routes
header('Access-Control-Allow-Origin: http://yourdomain.com/');
Related
I get a problem. I already read a lot of reference but still get error.
Access to font at 'http://192.168.0.1/fonts/fontawesome-webfont.woff2?v=4.7.0' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
What i have done?
First Effort
I try to make new file .htaccess in /public/font folder.
Inside .htaccess i write :
<FilesMatch "\.(ttf|otf|eot|woff|woff2)$">
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "*"
</IfModule>
</FilesMatch>
Second effort
I try to use Middleware, create new file call CORS.php
Inside CORS.php i write
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode as Middleware;
use Closure;
use Illuminate\Support\Facades\Response;
use Log;
class CORS extends Middleware {
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
Log::info("CORS 1");
$origin = $request->header('origin');
Log::info("Origin in CORS : $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'
// ];
$headers = [
'Access-Control-Allow-Origin' => $origin,
'Access-Control-Allow-Methods'=> 'GET, POST',
'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);
}
Log::info("CORS");
Log::info($response);
return $response;
}
}
Result :
First effort and Second Effort still not works. Second effort only
works for API request (if you add GET and OPTIONS in API).
My Question :
My goal is i want to access fontawesome from other Laravel Server.
What's my fault?
I am running laravel lumen php frameowrk 5.5.2 on localhost\8080 on my machine.I am running angular4 frontend locally on localhost\4200. When I run my application, I am able to connect to some Laravel apis through angular and get the data and also I can make changes to those apis. But when i try to connect to some other apis in Laravel through my front-end, I am getting this error in the browser console "Access to XMLHttpRequest at 'http://localhost:8080/ABC' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource."
So i referred to this link and made respective changes at the Laravel backend server code as mentioned by them:
https://gist.github.com/danharper/06d2386f0b826b669552#file-usage-md
But then, when i connect to Laravel apis, through angular, now I get this error:
"Access to XMLHttpRequest at 'http://localhost:8080/ABC' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status."
Also, do I have to make any changes to the angular front end code?
I cannot move forward because of this CORS blocking...Any help would be greatly appreciated.
This is my CorsMiddleware.php file in Laravel:
use Closure;
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;
}
}
This is my CatchAllOptionsRequestsProvider.php file in Laravel:
/**
* 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);
});
}
}
This is my app.php file where i register my provider and Cors middleware:
$app->register(App\Providers\CatchAllOptionsRequestsProvider::class);
$app->routeMiddleware(['auth' => App\Http\Middleware\Authenticate::class,]);
$app->middleware([App\Http\Middleware\CorsMiddleware::class]);
Do the following:
1. create the middleware
<?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)
{
$headers = [
'Access-Control-Allow-Origin' => '*',
'Access-Control-Allow-Methods' => 'POST, GET, OPTIONS, PUT, DELETE',
'Access-Control-Allow-Credentials' => 'true',
'Access-Control-Max-Age' => '86400',
'Access-Control-Allow-Headers' => 'Content-Type, Authorization, X-Requested-With'
];
if ($request->isMethod('OPTIONS'))
{
return response()->json('{"method":"OPTIONS"}', 200, $headers);
}
$response = $next($request);
foreach($headers as $key => $value)
{
$response->header($key, $value);
}
return $response;
}
}
2. Add the middleware to the app/Http/kernel.php (for laravel)
protected $middleware = [
//...... other middlewares
\App\Http\Middleware\CorsMiddleware::class
];
for lumen do this in bootstrap/app.php
$app->middleware([
App\Http\Middleware\CorsMiddleware::class
]);
DONE!!
I have api on localhost (xampp) / codeigniter and im trying to access it via angular 4 and the browser keeps showing this error in the console. api works fine in postman.
[Firefox]:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://lvh.me/ci-abc/api/get_alltasks. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
[Chrome]:
Failed to load http://lvh.me/ci-abc/api/get_alltasks: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:4200' is therefore not allowed
access.
I have tried changing API url to localhost and 127.0.0.1 as well but didn't work. I am a beginner developer so pardon me if im missing something.
Service function in Angular 4
gettasks()
{
return this.http.get('http://lvh.me/ci-abc/api/get_alltasks')
.map(res=>res.json());
}
API function in codeigniter
function get_alltasks_get()
{
{
$result = $this->todo_model->get_alltasks();
if ($result) {
$this->response($result, 200);
} else {
$this->response("No record found", 404);
}
}
}
It's not Angular problem, the problem caused because you're not in the same domain as your server is, for example, if you try to send a request to example.com from johndoe.com you will get the error and it's browser that blocks the request!
The browser first makes a header request and if the request is allowed, the next request with the real method type will be issued.
For CodeIgniter, try adding OPTIONS to the allowed methods.
header("Access-Control-Allow-Methods: GET, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type, Content-Length, Accept-Encoding");
Take a look at this answer
CORS on PHP
Browsers send specific HTTP headers for cross-site requests
initiated from within XMLHttpRequest or the Fetch API. It
also expects to see specific HTTP headers sent back with cross-site
responses.
An overview of these headers, including sample JavaScript code that
initiates requests and processes responses from the server, as well as
a discussion of each header, can be found in the HTTP Access Control
(CORS) article and should be read as a companion article to this
one.
and should be read as a companion article to this one. This
article covers processing Access Control Requests and
formulating Access Control Responses in PHP.
If you don't have access to configure Apache, you can still send the header from a PHP script. It's a case of adding the following to your PHP scripts:
<?php
header("Access-Control-Allow-Origin: *");
I've just spend sometime on this and i found out a couple things:
start with studying your request you do from angular to the backend. In the request headers there is a key called 'origin: ...' this is the origin that is asked for.
Codeigniter uses a concept called 'filters' which can be compared to laravel's middleware or angulars interceptors. They do something with the request. In this case add a header.
You need to register those filters in Config/Filters.php for the application to use them.
So here is what i did:
Create a new CorsFilter.php under App\Filters
use CodeIgniter\config\Services;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\Response;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Filters\FilterInterface;
class CorsFilter implements FilterInterface
{
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
{
}
public function before(RequestInterface $request, $arguments = null)
{
if (array_key_exists('HTTP_ORIGIN', $_SERVER)) {
$origin = $_SERVER['HTTP_ORIGIN'];
} else if (array_key_exists('HTTP_REFERER', $_SERVER)) {
$origin = $_SERVER['HTTP_REFERER'];
} else {
$origin = $_SERVER['REMOTE_ADDR'];
}
$allowed_domains = array(
'http://localhost:4200',
// your origin from request headers goes here
);
if (in_array($origin, $allowed_domains)) {
header('Access-Control-Allow-Origin: ' . $origin);
}
//these headers are always needed for an api call
header("Access-Control-Allow-Headers: Origin, X-API-KEY, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method, Access-Control-Allow-Headers, Authorization, observe, enctype, Content-Length, X-Csrf-Token");
header("Access-Control-Allow-Methods: GET, PUT, POST, DELETE, PATCH, OPTIONS");
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Max-Age: 3600");
header('content-type: application/json; charset=utf-8');
$method = $_SERVER['REQUEST_METHOD'];
//this handles the required 'ok' for the preflight check
if ($method == "OPTIONS") {
header("HTTP/1.1 200 OK CORS");
die();
}
}
}
register the filter in App\config\Filters.php
namespace Config;
use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Filters\CSRF;
use CodeIgniter\Filters\DebugToolbar;
use CodeIgniter\Filters\Honeypot;
use CodeIgniter\Filters\InvalidChars;
use CodeIgniter\Filters\SecureHeaders;
use App\Filters\CorsFilter;
class Filters extends BaseConfig
{
/**
* Configures aliases for Filter classes to
* make reading things nicer and simpler.
*
* #var array
*/
public $aliases = [
'csrf' => CSRF::class,
'toolbar' => DebugToolbar::class,
'honeypot' => Honeypot::class,
'invalidchars' => InvalidChars::class,
'secureheaders' => SecureHeaders::class,
'cors' => CorsFilter::class
];
/**
* List of filter aliases that are always
* applied before and after every request.
*
* #var array
*/
public $globals = [
'before' => [
'cors'
// 'honeypot',
// 'csrf',
// 'invalidchars',
],
'after' => [
'toolbar',
// 'honeypot',
// 'secureheaders',
],
];
/**
* List of filter aliases that works on a
* particular HTTP method (GET, POST, etc.).
*
* Example:
* 'post' => ['foo', 'bar']
*
* If you use this, you should disable auto-routing because auto-routing
* permits any HTTP method to access a controller. Accessing the controller
* with a method you don’t expect could bypass the filter.
*
* #var array
*/
public $methods = [];
/**
* List of filter aliases that should run on any
* before or after URI patterns.
*
* Example:
* 'isLoggedIn' => ['before' => ['account/*', 'profiles/*']]
*
* #var array
*/
public $filters = [];
}
Now every request from the frontend is allowed into the backend. Hope this makes sense and helps anyone struggling with this.
So I'm trying to create an API using Laravel, everything was going well until it came to that point where I have to connect it with Angular on another subdomain. I'm using JWT token-based auth which works fine.
I have created a CORS middleware 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)
{
return $next($request)
->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT, DELETE')
->header('Access-Control-Allow-Credentials', 'true')
->header('Access-Control-Max-Age', '10000')
->header('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With');
}
}
Added in Kernel.php and created Route group like this:
Route::group(['middleware' => 'cors'], function () {
Route::group(['prefix' => 'api/v1'], function() {
Route::get('/test', 'MemberController#test');
});
});
I'm trying to create a call that checks if user is authenticated and returns that to angular app so the app knows what to show.
I trued like this:
public function test()
{
if(Auth::check()){
echo "logged in";
} else {
echo "nuno";
}
}
But that returns the page without CORS headers, but if I remove "else" statement and only leave "if auth" it will return the page with headers.
Also, another problem I have is that JWT returns 400 if the token is invalid or not supplied.
The dreaded CORS Error:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading
the remote resource at http://localhost/mysite/api/test. (Reason: CORS
header 'Access-Control-Allow-Origin' missing).
Laravel route:
$router->group(['prefix' => 'api', 'middleware' => 'cors'], function ($router) {
$router->get('/test', 'MyController#myMethod');
});
Laravel Cors Middlware:
public function handle($request, Closure $next)
{
header('Access-Control-Allow-Origin: *');
// ALLOW OPTIONS METHOD
$headers = [
'Access-Control-Allow-Methods' => 'POST, GET, OPTIONS, PUT, DELETE',
'Access-Control-Allow-Headers' => 'Content-Type, X-Auth-Token, Origin, Authorization'
];
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;
}
Laravel Kernel:
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'cors' => \App\Http\Middleware\CORS::class
];
Relevant .htaccess:
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
Relevant Vue.js:
new Vue({
el: '#app',
data: {
//data here
},
http: {
headers: {
"Authorization": "Basic " + "apiKeyHere"
}
},
methods: {
mymethod: function (e)
{
e.preventDefault();
this.$http.get('http://localhost/mysite/api/test').then(
function (response)
{
//do something
}
)
}
}
});
If I take out the Authorization header option the request works.
I've also tried https://github.com/barryvdh/laravel-cors but still no joy.
Any help appreciated!
Clearly not the ideal solution but it WORKS. I've added this to the top of my routes.php file:
header('Access-Control-Allow-Origin: *');
header( 'Access-Control-Allow-Headers: Authorization, Content-Type' );
It would be nice to get this working without a hack... alas.
UPDATE: It turned out to be IIS related. I ended up setting the headers in the web.config file and now CORS works without hacking the routes.php file.
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Headers" value="Origin, Authorization, X-Requested-With, Content-Type, Accept" />
<add name="Access-Control-Allow-Methods" value="POST,GET,OPTIONS,PUT,DELETE" />
</customHeaders>
</httpProtocol>
If you want to restrict access, you can add outbound rules:
<outboundRules>
<clear />
<rule name="AddCrossDomainHeader">
<match serverVariable="RESPONSE_Access_Control_Allow_Origin" pattern=".*" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="true">
<add input="{HTTP_ORIGIN}" pattern="(http(s)?://((.+\.)?somesite\.com|(.+\.)?anothersite\.org))" />
</conditions>
<action type="Rewrite" value="{C:0}" />
</rule>
</outboundRules>
I solve my problem just adding these line on my routes.php Laravel 5.2
For greater then 5.2 in routes/web.php
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE');
header('Access-Control-Allow-Headers: Content-Type, X-Auth-Token, Origin, Authorization');
OR register Cors middleware in global HTTP middleware stack
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\App\Http\Middleware\CorsMiddleware::class
];
Laravel 7 or lower:
Your middleware is ok but you need to register Cors middleware in global HTTP middleware stack.
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\App\Http\Middleware\CorsMiddleware::class
];
Laravel 8 or higher:
All CORS settings may be configured in your application's config/cors.php configuration file. The OPTIONS requests will automatically be handled by the HandleCors middleware that is included by default in your global middleware stack.
Link to the official documentation
The issue arises from the preflight request, indeed, but the way of handling requires some additional explanation, when we're talking about Laravel - mainly OPTIONS request is routed (something the other answers rather do PHP way, than Laravel way), so, you have to add this to your routes for it to be successfull:
Route::options('/{any}', function(){ return ''; })->where('any', '.*');
Now, let's cater for all other methods - create CORS middleware:
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)
{
return $next($request)
->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods', 'GET, POST, PATCH, PUT, DELETE');
}
}
And finally, for given route, use that middleware:
Route::put('/test', function(){ echo('test'); })->with('cors');
You can bypass this one without using any middleware like Barryvdh\Cors for Laravel which was not working properly with JWT AUTH , I have added the following statements in the index.php in Laravel just before the Kernel instantiation
header('Access-Control-Allow-Origin: http://localhost:8001');
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token,Authorization');
header('Access-Control-Allow-Credentials: true');
add this one before
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
this should work properly with JWT AUTH also. Kindly note that in Access-Control-Allow-Headers you should include Authorization otherwise your accesstoken will not be allowed with Authorization header therefore JWT AUTH will fail. Happy Coding.
I have solved my problem easily by adding headers in bootstrap/app.php
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: *');
header('Access-Control-Allow-Headers: *');
My solution:
$router->group(['prefix' => 'api', 'middleware' => 'cors'], function ($router){
$router->options('{param1?}/{param2?}/{param3?}', function () {});
});
This answer is based on this article.
barryvdh/laravel-cors middleware library, can be used to fix the problem(Cross-Origin Resource Sharing).
step 1 Install it:
composer require barryvdh/laravel-cors
step 2 Releasing vendor files of the library:
php artisan vendor:publish --provider="Barryvdh\Cors\ServiceProvider"
step 3 The command ran in step 2 will copy a cors.php file to config directory, which looks like this:
return [
/*
|--------------------------------------------------------------------------
| Laravel CORS
|--------------------------------------------------------------------------
|
| allowedOrigins, allowedHeaders and allowedMethods can be set to array('*')
| to accept any value.
|
*/
'supportsCredentials' => false,
'allowedOrigins' => ['*'],// ex: ['abc.com', 'api.abc.com']
'allowedHeaders' => ['*'],
'allowedMethods' => ['*'],// ex: ['GET', 'POST', 'PUT', 'DELETE']
'exposedHeaders' => [],
'maxAge' => 0,
];
For allowedOrigins the value can either be ['*'] which indicated that the origin of request can be from any domain, or an array of specific domains which can be the origins that we will allow to send request to our api, like this ['first.com', 'second.com', 'register.third.com']
and also allowedMethods can either be ['*'] or a list of allowed HTTP verbs for instance ['POST', 'GET']
step 4 Registering the cors middleware. Open app/Http/kernel.php and add the HandleCors class to $routeMiddleware like this:
protected $routeMiddleware = [
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'cors' => \Barryvdh\Cors\HandleCors::class, // add this line to enable cors to your routes
];
step 5 Now you can add the laravel-cors middleware to any route that you want. For instance in Routes/api.php I will do this:
Route::apiResource('category', 'CategoryController')->middleware('cors');
Route::apiResource('product', 'ProductController')->middleware('cors');
Even if it works to put your middleware directly into $middleware instead of $routeMiddleware or to simply define the headers globally in the app.php, it is a horrible decision, because it will expose all endpoints with the new CORS policy, in case you only want to make a part of your API public to third party solutions.
The better solution is to only allow OPTIONS calls to go through on all endpoints and still redirect other HTTP methods through the $routeMiddleware to be able to limit the CORS policy only on a subset of endpoints.
So, build two middlewares:
Cors.php
<?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)
{
return $next($request)
->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods', '*')
->header('Access-Control-Allow-Headers', '*');
}
}
OptionsCors.php
<?php
namespace App\Http\Middleware;
use Closure;
class OptionsCors
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if($request->isMethod('OPTIONS')) {
return $next($request)
->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods', '*')
->header('Access-Control-Allow-Headers', '*');
}
return $next($request);
}
}
app/Http/Kernel.php
<?php
namespace App\Http
{
class Kernel extends \Illuminate\Foundation\Http\Kernel
{
protected $middleware = [
// ...
'App\Http\Middleware\OptionsCors',
];
protected $middlewareGroups = [
'web' => [
// ...
],
'api' => [
'App\Http\Middleware\UseApiGuard',
'throttle:60,1',
'bindings'
]
];
protected $routeMiddleware = [
// ...
'cors' => 'App\Http\Middleware\Cors',
];
}
}
Now in your routes you have full control about what endpoints will be exposed with your tightened CORS policy:
Route::namespace('Api')->middleware(['cors'])->group(function () {
Route::get('api/im_open', 'TestController#ping');
});
Route::namespace('Api')->group(function () {
Route::get('api/im_closed', 'TestController#ping');
});