Enable CORS on Lumen API - ajax

I know it's a known issue but I've tried almost everything and I'm still stuck on this. I have a simple project structured like this:
[Client] => [Gateway] => [API]
Laravel 6 Lumen 6 Lumen 6
localhost:8000 localhost:8001 localhost:8002
Since I'm just started working on this project only to prove if this works I've disabled all auth stuff.
On my API I have a folder within public called uploads (Basically in http://localhost:8002/uploads/audio.amr) where I have 1 audio file (.amr) and I'm trying to play it from a client view.
Since html can't play .amr files, I had to use a plugin. And I'm using this one BenzAMRRecorder.
[Client side]
I make an ajax petition to get the url of the audio file. The client through guzzle connects with the gateway and the gateway also does it with the API and I successfully got the url http://localhost:8002/uploads/audio.amr.
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
url : 'client/get_url_audio',
type : 'GET',
data : {
},
dataType:'json',
success : function(data) {
/** Here's the way to play the file */
var amr = new BenzAMRRecorder();
amr.initWithUrl(data['url']).then(function() {
amr.play();
});
},
});
I successfully got the url but when the BenzAMRRecorder try to access to the url http://localhost:8002/uploads/audio.amr I got this error:
The error:
Access to XMLHttpRequest at 'http://localhost:8002/uploads/audio.amr' from origin 'http://localhost:8000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I've read a lot of ways to fix this and I added a CorsMiddleware on the API with a handle function as follows:
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;
}
And then on bootstrap/app.php added
$app->middleware([
App\Http\Middleware\Cors::class
]);
But I'm still getting the same error. The thing I thought is that, when the method amr.initWithUrl(data['url']) access to the API folder, it doesn't go to middleware and try to access directly to the folders without passing by the middleware but I don't know why. Can someone help me to solve this problem?
EDIT: I also tried with github.com/barryvdh/laravel-cors

Add the following in the .htaccess file from the server which holds the resource you are trying to access:
Header Set Access-Control-Allow-Origin "*"

I don't know if it works in Lumen, but for Laravel, I've had a lot of success using this neomerx/cors package.

You probably missed the header X-CSRF-TOKEN from your CORS middleware?
$headers = [
....
// You will need to add ALL headers sent from your client
'Access-Control-Allow-Headers' => 'Content-Type, Authorization, X-Requested-With, X-CSRF-TOKEN'
];

Related

how to solve cors Allow Access control in vue js and laravel application

I Have tried almost everything. My front end is developed in vue js . backend is in laravel. we have written api for another website from which we are trying to fetch data. If directly access that website Url it gives all the data but when i try to access it from my website with axios it gives me this error.
Access to XMLHttpRequest at 'https://example.com/api/tickets/fetch_tickets?page=undefined' from origin 'http://localhost:8000' has been blocked by CORS policy: Request header field x-requested-with is not allowed by Access-Control-Allow-Headers in preflight response.
that website form which i am trying to fetch data also build in laravel. i have created middleware and applied it on api routes. I added chrome extension Allow Cors with which it works fine but we cant ask every client to use that extension.
We access that url from other website which is accessing data nicely. only vue js app creating these issue.
Vue Code
getTickets() {
axios.get( 'example.com/api/tickets/fetch_tickets?page=' + this.pagination.current, {
}).then((response) => {
// console.log(res.data.data)
// this.desserts = res.data.data;
// this.loadingprop = false;
this.desserts = response.data.data;
this.pagination.current = response.data.current_page;
this.pagination.total = response.data.last_page;
console.log(response.data.data);
}).catch((err) => {
this.handleErrors(err.response.data.errors);
})
.then(() => {
this.loading = false;
});
}
other website's routes
Route::group(['middleware' => ['api','cors']], function () {
Route::group(['prefix' => 'tickets'], function () {
Route::post('/store_ticket_auth', 'TicketApiController#storeTicketAuth'); //enter ticket auth
Route::get('/fetch_tickets', 'TicketApiController#fetchTickets'); //get all tickets
Route::get('/fetch_replies/{ticket_id}', 'TicketApiController#fetchTicketReplies'); // get all replies by ticket id
Route::post('/send_reply', 'TicketApiController#sendTicketReply'); // Send reply
Route::post('/update_ticket', 'TicketApiController#updateTicketStatus'); // Update Status
});
});
Do I need to add this on my cuurent project too?
return $next($request)
->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
I think the issue is on client side but dont know why it is not working.
I tried all answers on stackoverflow but nothing works
I have to add these lines in my index.php file of laravel
header("Access-Control-Allow-Origin: *");
//header("Access-Control-Allow-Methods", "DELETE, POST, GET, OPTIONS");
header("Access-Control-Allow-Headers:*");
if ($_SERVER['REQUEST_METHOD'] == "OPTIONS") {//send back preflight request response
return "";
}
Solved my issues by commenting out:
// window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
in resources/js/bootstrap.js
The error is telling you that the server won't allow the client to use a x-requested-with header.
In php you can do this to allow the server to accept that header:
header('Access-Control-Allow-Headers: X-Requested-With');
If you want the easy way you can use laravel-cors
You can follow the installation step and add this code in your config/cors.php
'allow_origins' => [
'https://yourfrontendrequest.url',
],
Install Moesif Origin & CORS Changer Chrome extension and
Then go to resources/js/bootstrap.js and comment out this line // window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
you can disable same origin policy in chrome
press win + R
and then copy this :
chrome.exe --user-data-dir="C://Chrome dev session" --disable-web-security

CORS Access to XMLHttpRequest at X from origin has been blocked by CORS policy

CORS Access to XMLHttpRequest at X from origin has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
Hi, I am struggling to resolve my problems with CORS denying interaction of my Vue component with an external API with axios since it returns this error. I've tried both using Barryvdh's Cors header support and making a middleware and custom route. It simply won't work. Everything that has been mentioned in README.md in Barryvdh's repo has been done and unfortunately, this problem won't get resolved by any means necessary.
Here is the code, even though I don't think there's need to show since it's exactly the same as mentioned in the repo;
inside Kernel.php:
protected $middleware = [
\Barryvdh\Cors\HandleCors::class,
inside app.php (providers array):
Barryvdh\Cors\ServiceProvider::class,
config/cors.php:
'supportsCredentials' => false,
'allowedOrigins' => ['*'],
'allowedHeaders' => ['*'],
'allowedMethods' => ['*'], // ex: ['GET', 'POST', 'PUT', 'DELETE']
'exposedHeaders' => [],
'maxAge' => 0,
Here's the axios get call (I've replaced my token with 'TOKEN')
methods: {
loadWeatherData: function() {
axios.get( 'http://api.openweathermap.org/data/2.5/weather?q=London&mode=json&units=metric&appid=TOKEN' )
.then( function( response ) {
console.log( 'radi' );
}).catch( errors => {
console.log( errors+' ne radi');
});
}
},
I've composer dump-ed, nothing affected resolving the problem.
Is there something I am doing wrong and are there any solutions for this problem? Thanks in advance!
The problem here seems to be that axios likes to send its own default headers, and these don't pass the preflight check for your external request. To fix this, you will need to remove the offending headers.
I was able to recreate your error, and also to bypass the CORS issue using the code below.
let url = 'https://api.openweathermap.org/data/2.5/weather?q=London&mode=json&units=metric&appid=TOKEN';
// create a new instance so we don't delete the headers for other requests
let instance = axios.create();
// delete headers if existing
delete instance.defaults.headers.common['Accept'];
delete instance.defaults.headers.common['X-Requested-With'];
delete instance.defaults.headers.common['X-CSRF-TOKEN'];
// use the new axios instance to make your get request
instance.get(url)
.then(function(response) {
console.log(response);
}).catch( errors => {
console.log(errors + ' ne radi');
});
Hope this helps and good luck!
You can add into TrustHosts.php Middleware without doing anything extra. Read more from here https://stackoverflow.com/a/70361284/2612926

Method PUT is not allowed by Access-Control-Allow-Methods in preflight response vue-laravel App

I am new in vue. For ajax request I am using axios and for back-end I am using Laravel. Whenever I send a POST and GET request it's works fine. But while trying to send a PUT Request its showing Method PUT is not allowed by Access-Control-Allow-Methods in preflight response vue-laravel App. I had read lots of answer in Stackoverflow and github but none of them worked for me.
Here is the client side code:
axios.put('http://127.0.0.1:8000/api/photo/6', this.photo, { headers: getHeader() })
.then(response => {
console.log(response.data.message);
}).catch(err => {
this.errors = err.response.data.errors;
});
Here is CROSS middleware code:
//allowed client
//now only for localhost vue cli
$domains = ['http://localhost:8080'];
if(isset($request->server()['HTTP_ORIGIN'])){
$origin = $request->server()['HTTP_ORIGIN'];
if(in_array($origin, $domains)){
header('Access-Control-Allow-Origin: '.$origin);
header('Access-Control-Allow-Headers: Origin, Content-Type, Authorization');
}
}
return $next($request);
Try this in backend :
app/Http/Middleware/Cors.php
public function handle($request, Closure $next)
{
return $next($request)
->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE,
OPTIONS');
}
app/Http/Kernel.php $routedMiddleware array add
'cors' => \App\Http\Middleware\Cors::class,
Route/api.php
Route::group(['middleware' => 'cors'], function () {
Route::put('/v1/employees', 'Employees#store');
});
Particular GET, HEAD and POST HTTP requests do not trigger the CORS preflight OPTIONS check. They are called Simple Requests. They only send a subset of HTTP headers along. Any other additional header, like an Authorization header (think JWT authentication), will trigger a preflight OPTIONS request. The details on this can be found on https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
I think the easiest way for you to work with this, is to use the laravel-cors package on the backend (see https://github.com/barryvdh/laravel-cors).
While doing development, you can simply be very permissive by setting allowedOrigins, allowedHeaders and allowedMethods to *. Later on, during testing and subsequently production, you should tune it to be more strict. By that time you'll have a much better hang of CORS concepts, and then you can configure it fully to your needs.

Laravel API return HTTP 0 error

I access my Laravel API Endpoints with respective Params its return HTTP 0 Error.
$(document).ready(function() {
$('#customer_name').change(function() {
$.ajax({
url: "http://acmexponents.com/api/v1/untransportamts",
dataType: "json",
type: "POST",
data: {
'pickupaddress': 'Ampang Jaya Selangor Malaysia',
'deliveryaddress': 'Bukit Bintang Kuala Lumpur Federal Territory of Kuala Lumpur Malaysia',
'pickupdate': '2018-01-24',
'pickuptime': '14:30',
'vehicletype': 2,
'vehiclesize': 3,
},
success: function(response) {
$("#customer_address").val(json);
},
error: function(jqXHR, textStatus, errorThrown) {
alert(jqXHR.status);
alert(textStatus);
alert(errorThrown);
}
});
});
});
Full Error Text :
Javascript returned an HTTP 0 error. One common reason this might
happen is that you requested a cross-domain resource from a server
that did not include the appropriate CORS headers in the response.
Better open up your Firebug...
How to resolve It.
What is CORS (Cross-origin resource sharing):
We understand that Javascript is restricted by same origin policy, i.e, could not make request that crossed its origin (different domain name etc). This is troublesome for web owners that is having different domain name as their web service although everything is owned by the same owner.
To bypass same origin policy, CORS is introduced such that a web server can explicitly allow javascript from making requests although the origin has crossed. It can be achieved by either from Apache, PHP, or any http proxies, whichever is capable in sending response headers will be able to implement this mechanism.
https://en.wikipedia.org/wiki/Cross-origin_resource_sharing
There are couple ways sending CORS headers to your app. One option is to include a middleware that emits CORS headers to every requests. This class ensured your server allow everyone to make request to this server (not very recommended, tweak as you like).
Create new file app/Http/Middleware/CorsMiddleware.php
class CorsMiddleware
{
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;
}
}
If you are using Lumen, include the middleware in your app.php:
$app->middleware([
//...
App\Http\Middleware\CorsMiddleware::class,
//...
]);
CORS Middleware source code: https://gist.github.com/danharper/06d2386f0b826b669552#gistcomment-1694593

Vuejs and Laravel Post Request CORS

I dont get it. I am struggling with this since hours
I am using Vue.js with Laravel and try to make a POST Request to an external API.
But i am always getting a CORS error on my Vue POST Request
methods: {
chargeCustomer(){
this.$http.post('/api/chargeCustomer', this.payment).then(function (response) {
console.log(response.data)
},function (response) {
console.log(response.data)
});
}
}
ERROR
MLHttpRequest cannot load
https://www.mollie.com/payscreen/select-method/JucpqJQses. No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'https://payment.dev' is therefore not allowed
access.
I installed the Laravel CORS Package for my Backend and added the middleware to my route e.g
Route::group(['middleware' => 'cors'], function(){
Route::post('/api/chargeCustomer', 'Backend\PaymentController#chargeCustomer');
});
But i am still getting the error. I also tried to add the Vue Headers with
Vue.http.headers.common['Access-Control-Allow-Origin'] = '*';
Vue.http.headers.common['Access-Control-Request-Method'] = '*';
With the same result/error.
Could someone tell me what i am doing wrong?
You need to set up the CORS headers from the middleware. Maybe you need some extra setup?
Anyway, you can create your own middleware and set up the CORS headers in the handle() method like the following example:
public function handle($request, Closure $next)
{
return $next($request)
->header('Access-Control-Allow-Origin', 'http://yourfrontenddomain.com') // maybe put this into the .env file so you can change the URL in production.
->header('Access-Control-Allow-Methods', '*') // or specify `'GET, POST, PUT, DELETE'` etc as the second parameter if you want to restrict the methods that are allowed.
->header('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Authorization') // or add your headers.
}
Add your custom middleware to the global $middleware array (under CheckForMaintenanceMode::class) in the Kernel.php class and you should be good to go.
Other way (without creating a new laravel middleware) is add these headers at the begining of your routes.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');
and add this before your interceptors on vue:
Vue.http.options.crossOrigin = true

Resources