Lumen - CORS missing allow origin but request suceed - php

I have a problem with my application Lumen-VueJs
I make a request and the request status is 200 and I receive what I want but on the 'network' the request is blocked. ( screen )
I have on my app a CorsMiddleware that is like that and that is also added in the bootstrap/app.php
<?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;
}
}
These are the headers of my request :
I don't understand why I have that error that must be authorized by my Middleware
Thanks in advance for your help !

Summarizing our discussion in the chat, the issue your browser is complaining about is correct. The Access-Control-Allow-Origin header is not sent.
This is because your middleware was not called as you have added your middleware to $app->routeMiddleware with key cors. I assume there is no route that is called cors. From Lumen's GitHub:
These can be global middleware that run before and after each request [$middleware] into a route or middleware that'll be assigned to some specific routes [$routeMiddleware].
As your CORS middleware should be called for all requests, you need to add it to $app->middleware.

Related

Laravel 5.5 CORS issue when loading FontAwesome 4.7.0

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?

how to add log when call http request in laravel?

I need to add log after call http request in big project like this?
$response = Http::get('http://example.com');
Log::info(`add request and header and response`);
i want to define global log for all http requests.
i need to define macro like this :
\Illuminate\Support\Facades\Http::macro('log',function(){
Log::info(`add request and header and response`);
});
and call http request like this:
$response = Http::get('http://example.com')->log();
Http is built on Guzzle, which accepts cURL options. One of those is CURLOPT_VERBOSE, rewritten as debug, which will send request data to either the screen or a log file. It accepts a file resource as an option:
$response = Http::withOptions(['debug'=>true])->get('http://example.com');
Or
$fp = fopen(storage_path('http_log.txt'), 'w+');
$response = Http::withOptions(['debug'=>$fp])->get('http://example.com');
If you need more data than that, you can extend the Http class and add your own logging methods to it.
See https://laravel.com/docs/8.x/http-client#guzzle-options and https://docs.guzzlephp.org/en/stable/request-options.html#debug for information on the debug option.
You can use a Terminable Middleware to log the HTTP response after it has already been sent to the browser.
To get the total time you can compare the result of microtime(true) with the laravel constant LARAVEL_START. That constant is defined at bootstrap/autoload.php, the entry point of the framework
For instance, here is a middleware that will log in both HTTP headers and system log the response time. Since you have access to the current request in the $request variable you could leverage that to also log any parameters you want
<?php // File: app/Http/Middleware/MeasureResponseTime.php
namespace App\Http\Middleware;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class MeasureResponseTime
{
/**
* Handle an incoming HTTP request.
*
* #param \Symfony\Component\HttpFoundation\Request $request
* #param \Closure $next
* #return \Symfony\Component\HttpFoundation\Response
*/
public function handle($request, \Closure $next)
{
$response = $next($request);
// Add response time as an HTTP header. For better accuracy ensure this middleware
// is added at the end of the list of global middlewares in the Kernel.php file
if (defined('LARAVEL_START') and $response instanceof Response) {
$response->headers->add(['X-RESPONSE-TIME' => microtime(true) - LARAVEL_START]);
}
return $response;
}
/**
* Perform any final actions for the request lifecycle.
*
* #param \Symfony\Component\HttpFoundation\Request $request
* #param \Symfony\Component\HttpFoundation\Response $response
* #return void
*/
public function terminate($request, $response)
{
// At this point the response has already been sent to the browser so any
// modification to the response (such adding HTTP headers) will have no effect
if (defined('LARAVEL_START') and $request instanceof Request) {
app('log')->debug('Response time', [
'method' => $request->getMethod(),
'uri' => $request->getRequestUri(),
'seconds' => microtime(true) - LARAVEL_START,
]);
}
}
}

How to add CORS headers for OPTIONS preflight request in Laravel Lumen 5.5.2 with angular4 as front end

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!!

Laravel : No 'Access-Control-Allow-Origin' header [duplicate]

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/');

Laravel CORS headers not shown if user is not auth'ed

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.

Categories