CORS issue with Vue.js - javascript

I'm using:
Vue 2.0.3
vue-router 2.0.1
vuex 0.8.2
vue-resource 0.7.0
And after trying to login to my page when using remote API, not the locally run one, I get cors error like following
vue-resource.common.js?2f13:1074 OPTIONS
https://mywebsite/api/auth/login
(anonymous function) # vue-resource.common.js?2f13:1074
Promise$1 # vue-resource.common.js?2f13:681
xhrClient # vue-resource.common.js?2f13:1033
Client # vue-resource.common.js?2f13:1080
(anonymous function) # vue-resource.common.js?2f13:1008
XMLHttpRequest cannot load https://mywebsite/api/auth/login.
Response to preflight request doesn't pass access control check:
No 'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:8080' is therefore not allowed
access. The response had HTTP status code 415.
Now I have API running in Azure, and since it allows me to test my calls from Postman, I am quite sure the CORS headers are set properly on backend.
Not so sure about the Vue and the front.
I have situation like this in config files:
export const API_ROOT = 'https://mywebsite/api/'
export const AuthResource = Vue.resource(API_ROOT + 'auth{/action}')
than i.e I am calling this action like:
login: function (userData) {
return AuthResource.save({action: 'login'}, userData)
}
Finally as I am checking auth in login via token in vuex submodule I have
just a simple header check-up state.
var updateAuthHeaders = () => {
var token = JSON.parse(localStorage.getItem("auth_token"))
if (token != null){
Vue.http.headers.common['Authorization'] = token
}else{
Vue.http.headers.common['Authorization'] = null
}
}
I have tried adding Vue.http.headers.common['Access-Control-Allow-Origin'] = true here, but did not help the case.
Any idea? What am I doing wrong.. I suppose it will not work for other calls also if it doesn't work for login.

You face this error when the API url and client url aren't the same. Vue CLI 3 (and in the core of it, Webpack) allows you to proxy your API url to your client url.
Inside vue.config.js file add following lines:
// vue.config.js
module.exports = {
// options...
devServer: {
proxy: 'https://mywebsite/',
}
}
And then send your ajax calls to http://localhost/api/.
You can read the full article here:
How to deal with CORS error on Vue CLI 3?

1) Be sure that server sends Access-Control-Allow-Origin "*" header.
2) Vue.http.headers.common['Access-Control-Allow-Origin'] = true, Vue.http.headers.common['Access-Control-Allow-Origin'] = '*' and etc. don't needed in the client request.
3) Vue.http.options.emulateJSON = true should helps if 1 and 2 points already are ok, but vue-resource fails with status 0. Also, try to remove (if they exist) Vue.http.options.credentials = true and
Vue.http.options.emulateHTTP = true.

While you can add Access-Control-Allow-Origin: * to your server response (in this case IIS) but this is very much advised against.
What's happening here is that your client is http://localhost and it is trying to access https://mywebsite/api/ which means they're not from the same origin
If you add Access-Control-Allow-Origin: * you will be allowing the entire world to hit your API endpoint.
I'd suggest making your access control server headers Access-Control-Allow-Origin: *.mysite and make a vhost for your localhost to use dev.mysite or similar.
This will allow your "localhost" to access your API without issues.
You could also add localhost to a whitelist, but this is also not without its own security implications, and it doesn't work everywhere anyway.
So, in short, make a vhost for your localhost that's in the same domain as your REST service and your issue should be resolved.
Once you go live you should remove the *.mysite part and use as specific a domain as possible on your whitelist.
Good luck!

Greater possibility is that CORS is not enabled on the IIS. This can be enabled by modifying the web.config file in the application root folder in IIS as follows:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
</system.webServer>
</configuration>
Note: This method will allow anyone to reach the API endpoint and hence shouldn't be adopted on a production environment but only on a development environment.

You need a vue.config.js file at the root of your project and inside of the vue.config file you need to define your proxy within a devServer object
module.exports = { devServer: { proxy: 'https://exampledomain.com/api/'}};. Within your axios.post you can now make request by simply doing https://exampledomain.com/api/login

Just attach these in the response to your all API's
res.header('Access-Control-Allow-Origin','*');
res.header('Access-Control-Allow-Methods','GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.header('Access-Control-Allow-Headers','Origin,Content-Type,X-Requested-With,Accept,Authorization');

Related

Why is the proxy inside package.json not working in my React application?

I am currently trying to perform a simple fetch instruction in my React application, though, the actual url always ends up being that of the React application itself.
The React app is hosted at localhost:3000, and the server I am trying to connect to is at localhost:8080.
In the package.json I have a proxy field like so:
"proxy": "http://localhost:8080"
Then I have a fetch somewhere like so:
fetch('/', { /* stuff... */ })
But when I check in my browser it says a fetch request happened to http://localhost:3000; in another application, it used to be that if you had a proxy, this would just go to localhost:8080, but not this time.
I tried stuff like deleting the node_modules folder and package-lock.json, but that did not do anything (also did a npm install afterward). If I do this:
fetch('http://localhost:8080', { /* stuff... */ })
The url seems to be the correct one, though I get all sorts of random errors which I just do not understand:
Access to fetch at 'http://localhost:8080/' from origin 'http://localhost:3000' 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. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
I have never heard of CORS, perhaps this is new? So I have two questions really:
How to get my React proxy to work?
How do I get rid of this CORS stuff? I am running both servers myself so "access control checks" is a whole load of bogus...
Cheers!
For the proxy to handle a request, the endpoint you are calling shouldn't be handled by your React development server. For example, instead of fetch('/'), which is the endpoint that sends your React index.html file, your API should be at something like fetch('/api/').
Like the doc says:
To tell the development server to proxy any unknown requests to your API server in development, add a proxy field to your package.json, for example: "proxy": "http://localhost:8080".
This way, when you fetch('/api/todos') in development, the development server will recognize that it’s not a static asset, and will proxy your request to http://localhost:8080/api/todos as a fallback. The development server will only attempt to send requests without text/html in its Accept header to the proxy.
If it's still not working, you can switch to configuring the proxy manually, which is the second way to set up a proxy that Create React App talks about.
For that, first, remove the proxy you have in package.json, keep it as it's the rule for the endpoint I talked about above, then:
npm install http-proxy-middleware --save-dev
And finally, create a src/setupProxy.js file:
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/api', // 👈🏽 your API endpoint goes here.
createProxyMiddleware({
target: 'http://localhost:8080', // 👈🏽 your API URL goes here.
changeOrigin: true,
})
);
};
With that, you should be good to go. And about CORS, it's not new. You can read about it on mdn if you like.
No bro, that's how it's supposed to work. Add a route listener, say "/api", to your server and then call fetch('/api') from the client.
In the browser it will show up as http://localhost:3000/api even though your server is running on 8080.

API working in localhost but not working while uploading in server

I have created a website example.com which have 2 section called "service" & "ideas" are dynamic data. Which are coming from http://api.example.com/ourservice.json & http://api.example.com/ideas.json
in my project while I am running it in localhost it's fetching those data from the API, But when I uploaded the react build folder in server it's not fetching those data.
Is there anything I am missing? Is it the API's problem?
in nginx of the api.example.com's config file I have this config
server {
# Binds the TCP port 80.
listen 80;
# Root directory used to search for a file
root /var/www/html/example_static_api;
# Defines the file to use as index page
index index.html index.htm;
# Defines the domain or subdomain name.
# If no server_name is defined in a server block then
# Nginx uses the 'empty' name
server_name api.example.com;
location / {
# Return a 404 error for instances when the server receives
# requests for untraceable files and directories.
try_files $uri $uri/ =404;
add_header Access-Control-Allow-Origin *;
}
}
Is there anything I am missing!
The following link explains the reason for this problem and how to fix it. In short, I want to tell you that because the services you are calling do not have an ssl certificate and must be called https, you can easily see the error in the browser console
How to fix "insecure content was loaded over HTTPS, but requested an insecure resource"
After searching on StackOverflow I found the answer, there was 2 way to solve it. The first thing is adding SSL to the API URL.
and the second thing which was originally answered here by #buzatto.
"that's related to the fact that the api is served at http while your site is loaded https, so the browser blocks the request.
since you have no control over the fact that the 3rd party api, you can solve the issue adding the meta tag <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests"> "

Experiencing CORS issue when using an external node module in React

Problem
I'm using the howlongtobeat npm module in my React app, however when I do a search query as documented in the howlongtobeat docs I get the following CORS error in the console:
Access to XMLHttpRequest at 'https://howlongtobeat.com/search_results.php' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Here's my basic React app that I've been testing in:
import { HowLongToBeatService, HowLongToBeatEntry } from "howlongtobeat";
let hltbService = new HowLongToBeatService();
function App() {
hltbService.search("halo").then((result) => console.log(result));
return (
<div>something</div>
);
}
export default App;
Things I've Tried
I tested using the howlongtobeat node module in a Vanilla JavaScript file and that worked. So this issue seems to only be effecting me in React.
I tried the Chrome plugin Allow CORS: Access-Control-Allow-Origin and that fixes it locally, but obviously won't work in production (I'm trying to deploy to GitHub Pages).
I tried modifying the URL in the node package's js file to use the cors-anywhere proxy, but my app didn't seem to be picking up the changes I made to the node module's file.
I tried adding a proxy entry into my package.json (e.g. "proxy": "localhost:3000"), but that doesn't seem to work. I'm also not sure what URL I'm supposed to enter here (I tried https://howlongtobeat.com as well as the cors-anywhere proxy I hosted from above.
Any ideas on how I can fix this?
The web service you're using is preventing other sites from accessing its data client-side. Without the appropriate Access-Control-* headers from that service, you won't be able to do this directly.
I tried adding a proxy entry into my package.json (e.g. "proxy": "localhost:3000")
You're on the right path, but unless you're actually running a server that is reading this config, it won't matter.
You need to run some sort of proxy server to proxy the data to an origin you can control, so that your page is hosted from either the same origin, or that you have something like Access-Control-Allow-Origin: * in the response headers.
See also: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

Access Control Origin Header error using Axios

I'm making an API call using Axios in a React Web app. However, I'm getting this error in Chrome:
XMLHttpRequest cannot load
https://example.restdb.io/rest/mock-data. No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:8080' is therefore not allowed
access.
{
axios
.get("https://example.restdb.io/rest/mock-data", {
headers: {
"x-apikey": "API_KEY",
},
responseType: "json",
})
.then((response) => {
this.setState({ tableData: response.data });
});
}
I have also read several answers on Stack Overflow about the same issue, titled Access-Control-Allow-Origin but still couldn't figure out how to solve this. I don't want to use an extension in Chrome or use a temporary hack to solve this. Please suggest the standard way of solving the above issue.
After trying out few answers I have tried with this,
headers: {
'x-apikey': '59a7ad19f5a9fa0808f11931',
'Access-Control-Allow-Origin' : '*',
'Access-Control-Allow-Methods':'GET,PUT,POST,DELETE,PATCH,OPTIONS',
},
Now I get the error as,
Request header field Access-Control-Allow-Origin is not
allowed by Access-Control-Allow-Headers in preflight response
I'll have a go at this complicated subject.
What is origin?
The origin itself is the name of a host (scheme, hostname, and port) i.g. https://www.google.com or could be a locally opened file file:// etc.. It is where something (i.g. a web page) originated from. When you open your web browser and go to https://www.google.com, the origin of the web page that is displayed to you is https://www.google.com. You can see this in Chrome Dev Tools under Security:
The same applies for if you open a local HTML file via your file explorer (which is not served via a server):
What has this got to do with CORS issues?
When you open your browser and go to https://website.example, that website will have the origin of https://website.example. This website will most likely only fetch images, icons, js files and do API calls towards https://website.example, basically it is calling the same server as it was served from. It is doing calls to the same origin.
If you open your web browser and open a local HTML file and in that HTML file there is JavaScript which wants to do a request to Google for example, you get the following error:
The same-origin policy tells the browser to block cross-origin requests. In this instance origin null is trying to do a request to https://www.google.com (a cross-origin request). The browser will not allow this because of the CORS Policy which is set and that policy is that cross-origin requests is not allowed.
Same applies for if my page was served from a server on localhost:
Localhost server example
If we host our own localhost API server running on localhost:3000 with the following code:
const express = require('express')
const app = express()
app.use(express.static('public'))
app.get('/hello', function (req, res) {
// res.header("Access-Control-Allow-Origin", "*");
res.send('Hello World');
})
app.listen(3000, () => {
console.log('alive');
})
And open a HTML file (that does a request to the localhost:3000 server) directory from the file explorer the following error will happen:
Since the web page was not served from the localhost server on localhost:3000 and via the file explorer the origin is not the same as the server API origin, hence a cross-origin request is being attempted. The browser is stopping this attempt due to CORS Policy.
But if we uncomment the commented line:
const express = require('express')
const app = express()
app.use(express.static('public'))
app.get('/hello', function (req, res) {
res.header("Access-Control-Allow-Origin", "*");
res.send('Hello World');
})
app.listen(3000, () => {
console.log('alive');
})
And now try again:
It works, because the server which sends the HTTP response included now a header stating that it is OK for cross-origin requests to happen to the server, this means the browser will let it happen, hence no error.
Just to be clear, CORS policies are security features of modern day browsers, to protect people from harmful and malicious code.
How to fix things (One of the following)
Serve the page from the same origin as where the requests you are making reside (same host).
Allow the server to receive cross-origin requests by explicitly stating it in the response headers.
If using a reverse proxy such as Nginx, configure Nginx to send response headers that allow CORS.
Don't use a browser. Use cURL for example, it doesn't care about CORS Policies like browsers do and will get you what you want.
Example flow
Following is taken from: Cross-Origin Resource Sharing (CORS)
Remember, the same-origin policy tells the browser to block
cross-origin requests. When you want to get a public resource from a
different origin, the resource-providing server needs to tell the
browser "This origin where the request is coming from can access my
resource". The browser remembers that and allows cross-origin resource
sharing.
Step 1: client (browser) request When the browser is making a cross-origin request, the browser adds an Origin header with the
current origin (scheme, host, and port).
Step 2: server response On the server side, when a server sees this header, and wants to allow access, it needs to add an
Access-Control-Allow-Origin header to the response specifying the
requesting origin (or * to allow any origin.)
Step 3: browser receives response When the browser sees this response with an appropriate Access-Control-Allow-Origin header, the
browser allows the response data to be shared with the client site.
More links
Here is another good answer, more detailed as to what is happening: https://stackoverflow.com/a/10636765/1137669
If your backend support CORS, you probably need to add to your request this header:
headers: {"Access-Control-Allow-Origin": "*"}
[Update] Access-Control-Allow-Origin is a response header - so in order to enable CORS - you need to add this header to the response from your server.
But for the most cases better solution would be configuring the reverse proxy, so that your server would be able to redirect requests from the frontend to backend, without enabling CORS.
You can find documentation about CORS mechanism here:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
I had a similar problem and I found that in my case the withCredentials: true in the request was activating the CORS check while issuing the same in the header would avoid the check:
Reason: expected ‘true’ in CORS header ‘Access-Control-Allow-Credentials’
Do not use
withCredentials: true
but set
'Access-Control-Allow-Credentials':true
in the headers.
For Spring Boot - React js apps I added #CrossOrigin annotation on the controller and it works:
#CrossOrigin(origins = {"http://localhost:3000"})
#RestController
#RequestMapping("/api")
But take care to add localhost correct => 'http://localhost:3000', not with '/' at the end => 'http://localhost:3000/', this was my problem.
I had the same error. I solved it by installing CORS in my backend using npm i cors. You'll then need to add this to your code:
const cors = require('cors');
app.use(cors());
This fixed it for me; now I can post my forms using AJAX and without needing to add any customized headers.
For any one who used cors package change
const cors = require('cors');
app.use(cors());
to
const cors = require('cors');
app.use(cors({credentials: true, origin: 'http://localhost:5003'}));
change http://localhost:5003 to your client domain
Using the Access-Control-Allow-Origin header to the request won't help you in that case while this header can only be used on the response...
To make it work you should probably add this header to your response.You can also try to add the header crossorigin:true to your request.
First of all, CORS is definitely a server-side problem and not client-side but I was more than sure that server code was correct in my case since other apps were working using the same server on different domains. The solution for this described in more details in other answers.
My problem started when I started using axios with my custom instance. In my case, it was a very specific problem when we use a baseURL in axios instance and then try to make GET or POST calls from anywhere, axios adds a slash / between baseURL and request URL. This makes sense too, but it was the hidden problem. My Laravel server was redirecting to remove the trailing slash which was causing this problem.
In general, the pre-flight OPTIONS request doesn't like redirects. If your server is redirecting with 301 status code, it might be cached at different levels. So, definitely check for that and avoid it.
After a long time of trying to figure out how CORS works. I tried many way to fix it in my FE and BE code. Some ways CORS errors appearance, some ways the server didn't receive body from client, and other errors...
And finally got this way. I'm hoping this can help someone:
BE code (NodeJS + Express)
var express = require("express");
const cors = require("cors");
var app = express();
app.use(
cors({
origin: "*",
})
);
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
next();
});
// your routers and codes
My FE code (JS):
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Connection: 'Keep-Alive',
Authorization: `Bearer test`,
},
body: JSON.stringify(data),
});
I imagine everyone knows what cors is and what it is for.
In a simple way and for example if you use nodejs and express for the management, enable it is like this
Dependency:
https://www.npmjs.com/package/cors
app.use (
cors ({
origin: "*",
... more
})
);
And for the problem of browser requests locally, it is only to install this extension of google chrome.
Name: Allow CORS: Access-Control-Allow-Origin
https://chrome.google.com/webstore/detail/allow-cors-access-control/lhobafahddgcelffkeicbaginigeejlf?hl=es
This allows you to enable and disable cros in local, and problem solved.
npm i cors
const app = require('express')()
app.use(cors())
Above code worked for me.
You can create a new instance of axios with a custom config, and then use this new configured instance,
create a file with axios-configure.js, add this sharable exported method and use this preconfigured import, rather importing axios directly like we use traditionally,
import axios from 'axios';
import baseUrl from './data-service';
const app = axios.create({
baseURL: baseUrl,
headers: {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/json',
},
withCredentials: true
})
export default app;
use this exported function like,
import axios from '../YOUR_DIRECTORY/axios-configure';
axios.get();// wont throw cors
dont import axios from axios;
then use axios.get() it will dont throw cors worked for us,
NOTE this solution will work for them who facing CORS at local environment as local starts at 5000 and backend at 8080, but in production, build gets deployed from java 8080 no CORS in productions (Facing CORS at only local environment)
As I understand the problem is that request is sent from localhost:3000 to localhost:8080 and browser rejects such requests as CORS. So solution was to create proxy
My solution was :
import proxy from 'http-proxy-middleware'
app.use('/api/**', proxy({ target: "http://localhost:8080" }));
$ npm install cors
After installing cors from npm add the code below to your node app file. It solved my problem.
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())
I had a similar problem when I tried to create the React Axios instance.
I resolved it using the below approach.
const instance = axios.create({
baseURL: "https://jsonplaceholder.typicode.com/",
withCredentials: false,
headers: {
'Access-Control-Allow-Origin' : '*',
'Access-Control-Allow-Methods':'GET,PUT,POST,DELETE,PATCH,OPTIONS',
}
});
try it proxy
package.json add code:
"proxy":"https://localhost:port"
and restart npm enjoy
same code
const instance = axios.create({
baseURL: "/api/list",
});
You can use cors proxy in some specific cases - https://cors.sh
In node js(backend), Use cors npm module
$ npm install cors
Then add these lines to support Access-Control-Allow-Origin,
const express = require('express')
const app = express()
app.use(cors())
app.get('/products/:id', cors(), function (req, res, next) {
res.json({msg: 'This is CORS-enabled for a Single Route'});
});
You can achieve the same, without requiring any external module
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
},
"proxy": "http://localhost:8080",
"devDependencies": {
use proxy in package.json

Ionic v2 + CORS Preflight Access-Control-Allow-Methods

Having issues communicating with an external API via ionic serve and ionic run -l, essentially anything that uses a localserver.
I've followed the guide # http://blog.ionic.io/handling-cors-issues-in-ionic/, which provides an option for handling the issue in Ionic 1 projects, but I'm struggling to get it working in a v2 project.
Fetch API cannot load https://test.api.promisepay.com/items/100fd4a0-0538-11e6-b512-3e1d05defe79/make_payment. Method PATCH is not allowed by Access-Control-Allow-Methods in preflight response.
I have no control over how the API handles theses requests, as it is controlled by PromisePay.
Following the closest thing to a possible solution on StackOverflow: CORS with Firebase+IONIC2+Angularjs: No 'Access-Control-Allow-Origin' still exists
I've updated my ionic.config.json to
{
"name": "project",
"app_id": "xxxxxxx",
"proxies": [{
"path": "/api",
"proxyUrl": "https://test.api.promisepay.com"
}]
}
In the library that makes the http calls, I've updated the base URL to const PRE_LIVE_API = '/api';
The request method looks as follows:
let Requester = class Requester {
constructor() {
let config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
this.config = config;
const baseUrl = PRE_LIVE_API;
this.log(`API endpoint: ${ baseUrl }`);
this.client = _requestPromise2.default.defaults({
baseUrl: baseUrl,
auth: {
user: config.userName,
pass: config.token
},
headers: {
Accept: 'application/json',
Authorization: `basic ${ config.apiToken }`
},
resolveWithFullResponse: true
});
}
When making a call to the most basic of API endpoints /status/ I am now receiving the following error:
"Error: Invalid URI "/api/status""
It seems the proxy path isn't being passed through.
I was facing the same problem when I was trying to use the MailGun to send e-mails using REST API.
The solution is to use HTTP instead of http. ionic 2 provides the class [HTTP]: http://ionicframework.com/docs/v2/native/http/ .
In your projects root folder, run this command from the terminal:
ionic plugin add cordova-plugin-http
In your .ts file:
import { HTTP } from 'ionic-native';
Then, wherever you want to send the HTTP post/get using Basic Authentication, use this:
HTTP.useBasicAuth(username, password)
//replace username and password with your basic auth credentials
Finally, send the HTTP post using this method:
HTTP.post(url, parameters, headers)
Hope this helps! Good luck!
For Development purposes where the calling url is http://localhost, the browsers disallow cross-origin requests, but when you build the app and run it in mobile, it will start working.
For the sake of development,
1. Install CORS plugin/Extension in chrome browser which will help get over the CORS issue.
2. If the provider is giving a JSONP interface instead of a normal get/post, You will be able to get over the CORS issue.
I prefer using the 1st option as not a lot of api's provide a jsonP interface.
For Deployment,
You need not worry as building a app & running it in your mobile, you will not face the same issue.
Solved. Explicitly setting the BaseURL constant (PRE_LIVE_BASE) to http://localhost:8100/api resolves the issue. Now all requests are passed via the proxy alias and subvert the CORS issue.
The only downside of this approach, is that I had to change a variable that was part of a package in node_modules, which will be overwritten during any future updates. So I should probably create my own fork for a cleaner solution.

Categories

Resources