Node Express Cross Origin for $http.get() calling - angularjs

I did a simple node server , which I need it to be Cross Origin for $http.get() calling , so I add the required headers to the app.use as details in this answer. Finally the server code is -
var express = require('express');
var app = express();
var port = process.env.PORT || 3000;
app.use(express.static('.'));
app.all('/', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
next();
});
app.listen(port);
console.log('server runs on port: ' + port);
In my index.html there is angular $http.get() calling to a another origin -
$http.get('http://itunes.apple.com/search', {
term: 'johnson'
});
but still this calling is denied by the browser and return error -
XMLHttpRequest cannot load https://itunes.apple.com/search. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.
How could I make Cross Origin $http.get calling from the index.html correctly ?

You actually don't understand how cross-origin resource sharing works. Cross-origin requests should be allowed on server you making requests to, not on your server from which you are serving your page.
So, the answer is you can't make request to apple website if they haven't allowed you to do it.
P.S. You have allowed other websites to make request to your website by adding this code to your express app:
app.all('/', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
next();

Related

CORS error occurs when HTTPS applied to the my server using Let's Encrypt

I have a Digital Ocean Linux server.
I deployed my REST API and also front end in the same server.
My Back End runs using Node.JS and front end using AngularJS.
After enabling HTTPS, I changed all the REST URLs into HTTPS.
Like this :
var mainHost = "https://xxx.xxx.xxx.xx:7000/api";
Now I'm getting this CORS error :
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://xxx.xxx.xxx.xx:7000/api/user_manage/login. (Reason: CORS request did not succeed).
I am using Node.JS CORS plugin also.
var cors = require('cors');
var app = express();
app.use(cors());
This started when I added HTTPS and I tried many things. Including changing the .htaccess and adding some meta tags. Still no good. What is the reason for this ? Why CORS error comes after adding HTTPS ? Please help me to solve this.
This is the controller call for the service layer :
sessionService.getAllSessions(100, 0).then(function (data) {
console.log(data);
$scope.allSessions = data.data;
});
And this is the service layer :
getAllSessions: function (limit, offset) {
return $http({
method: "GET",
url: host.session_manage + '/session/' + limit + '/' + offset
}).then(function (response) {
return response.data;
});
}
I'm not using headers in the service call as you can see in the above section.
This is the server code snippet :
var express = require("express");
var bodyParser = require("body-parser");
var morgan = require("morgan");
var config = require("./config");
// var cors = require('cors');
var app = express();
// app.use(cors());
// app.use(cors({
// origin: 'https://xxxxxx.com'
// }));
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(); });
app.set('views', './app/views');
app.set('view engine', 'pug');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(morgan('dev'));
var session = require('./app/routes/session')(app, express);
app.use('/api/session_manage', session);
app.listen(config.port, function (err) {
if (err) {
console.log(err);
} else {
console.log("localhost:7000");
}
});
Thank you guys.
You are in production you don't want to allow CORS access for all origins but if you need to allow cross origin requests from some specified host(s) you can do add the following code:
server.use(cors({
origin: 'https://example.com'
}));
This will allow https://example.com to send cross origin requests to your Express server without the Same Origin Policy getting in the way.
You can also enable CORS for a single Express route
server.get('/endpoint', cors(), function (req, res, next) {
res.json({msg: 'This has CORS-enabled for only this route: /endpoint'})
})
If you want to allow multiple origins you need to use a function (for origin instead of a string) that dynamically set the CORS header depending on the origin making the request and a white list that you specify which contains the origin to allow.
var whitelist = ['http://example.com', 'http://othersite.com'];
var options = { origin: function (origin, callback) {
if (whitelist.indexOf(origin) !== -1) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
}
}
server.use(cors(options))

Enabling cors filters in two servers

I have two servers in the nodejs app.
I am using two servers http-server for static html file (i.e. index.html) and express for node APIs. Now I am getting the CORS filter error. even if I have enabled the cors filter on both the servers.
I have tried these combinations.
1. Enabling it on Node server using middleware.
i.e following code.
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");
res.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
next();
});
and on http-server using following command.
http-server --cors
I am still getting following error.
I am guessing here that enabling on both server won't work as both resources will have different CORS values. But how can I solve it? Any help would be appreciated.
Looking at the networks tab in the developer tools I can see following for the API request.
Update-1 tried cors package
I have tried following code samples with each time a server restart.
app.use(cors());
and this one too.
app.use(cors());
app.options('*', cors());
and this one with specific configuration.
app.use(cors());
var whitelist = ['http://localhost:8080']
var corsOptions = {
origin: function (origin, callback) {
if (whitelist.indexOf(origin) !== -1) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
}
}
app.options('*', cors(corsOptions));
Everytime I am getting the same response in output console.
These are the routes.
module.exports = function(app){
app.get('/get_tuna/:id', function(req, res){
tuna.get_tuna(req, res);
});
app.get('/add_tuna/:tuna', function(req, res){
tuna.add_tuna(req, res);
});
app.get('/get_all_tuna', function(req, res){
console.log('###### ++++++++++ 2 - This is called first');
tuna.get_all_tuna(req, res);
});
app.get('/change_holder/:holder', function(req, res){
tuna.change_holder(req, res);
});
app.get('/api/get_available_vault_balance/', function(req, res){
/// --------- 3
console.log('VAULT >> API is called >>> :) ');
vaultbackendservice.get_available_vault_balance(req, res);
});
}

Where should I write cors filter enabler code in angularjs

This is my js file, the following code is inside .controller
xhr.onreadystatechange = function () {
if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200){
$http.post(smsHorizon,'Access-Control-Allow-Origin', '*').then(function(res){
res.addheader('Access-Control-Allow-Origin', '*');
res.addheader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.addheader('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
if(res){
alert("OTP has been Send");
}
})
}
else{
}
}
Is this the way to code cors? Please help!!!
CORS request enabling always-on server side. You need to set CORS on response header.
CORS- How Internally Work
A resource makes a cross-origin HTTP request when it requests a resource from a domain or port which is different from the one which the first resource itself serves. For security reasons, browsers restrict cross-origin HTTP requests initiated from within scripts.
For example:
your app running on www.my-domain.com and its request for the resource on www.your-domain.com than browser do not allow to make the request within a script.
CORS- How To Resolve
suppose we made a request through angular script under domain www.my-domain.com is www.your-domain.com\id. This request hit on the server at endpoint /id on www.your-domain.com. So, at a time of rendering/sending a response by the server, it set 'Access-Control-Allow-Origin', '*' header in the response.
//java-jersey example
Response.status(200).entity(data)
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Methods", "GET")
.build();
//Nodejs Example
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())
app.get('/products/:id', function (req, res, next) {
res.json({msg: 'This is CORS-enabled for all origins!'})
})
For more details : https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

How to connect from angular to express server running on the same machine?

I am very new to express (and backend), and I am learning. So I mounted an express server on my machine by running express and npm install, and then overwriting the app.js with a simple code that serves something on /test
var express = require('express')
var app = express()
app.all('/*', function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Content-Type,X-Requested-With');
next();
});
app.get('/test', function (req, res) {
res.send('hi???');
});
app.listen(3100);
On my frontend, I am working with angular, it is running on localhost:3000, but when I run
function TestController ($http) {
var vm = this;
$http.get('http://localhost:3100/test')
.then(function (response) {
console.log(response);
});
}
It throws the following error:
XMLHttpRequest cannot load http://localhost:3100/test. Request header field Pragma is not allowed by Access-Control-Allow-Headers in preflight response.
I thought it could be a problem on the backend, but when I run
function TestController ($http) {
var vm = this;
var httpRequest = new XMLHttpRequest();
httpRequest.open('GET', 'http://localhost:3100/test', true);
httpRequest.send(null);
}
It won't throw any error, so I guess it is a problem with my angular configuration, but I cannot figure out where or what the problem is... how can I fix this? any help tweaking the backend or the frontend to fix this will be really helpful!
I already tried this, but it won't work, AngularJS POST Fails: Response for preflight has invalid HTTP status code 404 it doesn't makes any difference :(
Given the description of the problem, it was not about CORS, it had to do with headers not being handled correctly by the backend. Running the app on firefox, firebug suggests to add the token pragma to Access-Control-Allow-Headers... and then, another unkown header would jump up, now called cache-control so I only had to modify the app.js.
For anyone having this same problem, you just need to add the problematic headers to the string on 'Access-Control-Allow-Headers' :)
app.all('/*', function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers',
'Content-Type,X-Requested-With,cache-control,pragma'
+ otherHeadersSeparatedByComma);
next();
});

AngularJS POST request with JSON array data to Express server

I have a static AngularJS website and an Express server running on different domains. The site sends GET requests to the server with a file name as the parameter. The server then requests the file from an S3 bucket, that sends it with "binary/octet-stream" as the "Content-Type". It decrypts the data and sends it back to the site with the same "Content-Type", which then downloads the file. This all works well for single file requests, however I would like to be able to send the server an array of file names all at once, and then be able to download multiple files. I tried sending the file names as a JSON array but I get the error:
XMLHttpRequest cannot load http://localhost:3000/decrypt. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'file://' is therefore not allowed access.
In my server console, the request shows up as OPTIONS instead of POST. I've also made sure to include Access-Control-Allow-Origin: * in my response headers. How should I go about resolving this?
UPDATE:
I was able to resolve the CORS error by adding the following middleware on my router:
function allowCrossDomain(req, res, next) {
if ('OPTIONS' == req.method) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,PATCH,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
res.status(200).end();
}
else {
next();
}
}
However, I'm still not sure how to send multiple (for each file) "binary/octet-stream" in the response, and download them as files on the static site. Currently I am using angular-file-saver to save files from single requests.
You need to do a couple things in your server. First off are you using multer with bodyParser? Multer will allow you to add in post calls and will handle passing the data for you.
First AngularJS Post:
$http.post(baseUrl + "mypostmethod", o) //o is your object
.then(function successCallback(resp) {
console.log(resp)
}, function errorCallback(resp) {
console.log(resp)
});
Now as for your nodejs express setup, you want to ensure you are using all the proper modules. I will provide the basic list that I use in most of my projects. Also if you use req.headers.origin instead of * you sould no longer get the Access-Control-Allow-Origin error.
NodeJS:
var express = require('express'),
fs = require('fs'),
spdy = require('spdy'),
bodyParser = require('body-parser'),
multer = require('multer'),
helmet = require('helmet'),
upload = multer(), // this will allow you to pass your object into your post call with express
path = require('path'),
cookieParser = require('cookie-parser'),
request = require('request'),
app = express(),
http = require('http'),
formidable = require('formidable'); //Good for handling file uploads
app.use(helmet());
app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Origin', req.headers.origin);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,PATCH');
res.header('Access-Control-Allow-Headers', 'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version');
next();
});
These are the basic ones I use in almost all my programs. The most important with expressis bodyParser and multer since these will allow you to use your gets and post properly.
Here is an example of a post NodeJS:
app.post('/mypostmethod', upload.array(), function(req, res) {
var body = req.body,
sess = req.session;
res.send({
Status: "Success"
});
});
In this post when you use upload.array() that is utilizing multer and now req.body is the object you passed in with your angular post call.
Let me know if you have any question, I hope this helps.

Resources