Enable Cors in Gulp/BrowserSync - javascript

I've created an Angular project with yeoman's boilerplate code (generator-gulp-angular)
And now in my controller I'm trying to make a http request like this:
$http.get('http://food2fork.com/api/search?key='+key+'&page=1').then(function(response) {
vm.all = response.data;
});
But I keep getting this error:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://food2fork... (Reason: CORS header 'Access-Control-Allow-Origin' missing)
I did my research and found I needed to add this Access Control to my server,
using the middleware property, which I did, but I still keep getting an error here is my server.js file
var path = require('path');
var gulp = require('gulp');
var conf = require('./conf');
var cors = require('cors');
var browserSync = require('browser-sync');
var browserSyncSpa = require('browser-sync-spa');
var util = require('util');
var proxyMiddleware = require('http-proxy-middleware');
function browserSyncInit(baseDir, browser) {
browser = browser === undefined ? 'default' : browser;
var routes = null;
if(baseDir === conf.paths.src || (util.isArray(baseDir) && baseDir.indexOf(conf.paths.src) !== -1)) {
routes = {
'/bower_components': 'bower_components'
};
}
//here is where I added the middleware
var server = {
baseDir: baseDir,
middleware: function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
next();
},
routes: routes
};
browserSync.instance = browserSync.init({
startPath: '/',
server: server,
browser: browser
});
}
browserSync.use(browserSyncSpa({
selector: '[ng-app]'// Only needed for angular apps
}));
gulp.task('serve', ['watch'], function () {
browserSyncInit([path.join(conf.paths.tmp, '/serve'), conf.paths.src]);
});
gulp.task('serve:dist', ['build'], function () {
browserSyncInit(conf.paths.dist);
});
gulp.task('serve:e2e', ['inject'], function () {
browserSyncInit([conf.paths.tmp + '/serve', conf.paths.src], []);
});
gulp.task('serve:e2e-dist', ['build'], function () {
browserSyncInit(conf.paths.dist, []);
});
`
But still the error persists, any help?

You are requiring http-proxy-middleware but not using it !
If You want to resolve Cross Origin for all URL containing /api, first
you should forward your Angular requests to your BrowserSync Server
So
$http.get('http://food2fork.com/api/search?key='+key+'&page=1')
Should become
$http.get('/api/search?key='+key+'&page=1')
The BrowserSync will receive the call
In Browser relay the call to the real server in the back with
target :'http://food2fork.com/'
and add Cross Origin headers when the response comes back with
changeOrigin: true,
the full config becomes :
var proxyMiddleware = require('http-proxy-middleware');
const jsonPlaceholderProxy = proxyMiddleware('/api', {
target: 'http://food2fork.com/api',
changeOrigin: true,
logLevel: 'debug'
});
module.exports = function() {
return {
server: {
middleware: [jsonPlaceholderProxy],
baseDir: baseDir
}
};
};

You should add additional information on the server side which headers and methods are allowed. For example:
res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.setHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
or
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
This will tell the server to accept the headers send by the client (e.g. Origin) as well as the HTTP methods which you plan to support (e.g. GET).
For further informations on CORS see https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

Related

Problem facing in socket.io in sending 'Hello World' to console [duplicate]

I'm using node and socket.io to write a chat application. It works fine on Chrome but mozilla gives an error to enable the Cross-Origin Requests.
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://waleedahmad.kd.io:3000/socket.io/?EIO=2&transport=polling&t=1401964309289-2&sid=1OyDavRDf4WErI-VAAAI. This can be fixed by moving the resource to the same domain or enabling CORS.
Here's my code to start node server.
var express = require('express'),
app = express(),
server = require('http').createServer(app),
io = require('socket.io').listen(server),
path = require('path');
server.listen(3000);
app.get('/', function(req, res) {
res.sendfile(__dirname + '/public/index.html');
});
On the client side.
var socket = io.connect('//waleedahmad.kd.io:3000/');
Script tag on HTML page.
<script type="text/javascript" src="//waleedahmad.kd.io:3000/socket.io/socket.io.js"></script>
I'm also using .htaccess file in the app root directory. (waleedahmad.kd.io/node).
Header add Access-Control-Allow-Origin "*"
Header add Access-Control-Allow-Headers "origin, x-requested-with, content-type"
Header add Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"
Simple Server-Side Fix
❗ DO NOT USE "socketio" package... use "socket.io" instead. "socketio" is out of date. Some users seem to be using the wrong package.
❗ SECURITY WARNING: Setting origin * opens up the ability for phishing sites to imitate the look and feel of your site and then have it work just the same while grifting user info. If you set the origin, you can make their job harder, not easier. Also looking into using a CSRF token as well would be a great idea.
socket.io v3
docs: https://socket.io/docs/v3/handling-cors/
cors options: https://www.npmjs.com/package/cors
const io = require('socket.io')(server, {
cors: {
origin: '*',
}
});
socket.io < v3
const io = require('socket.io')(server, { origins: '*:*'});
or
io.set('origins', '*:*');
or
io.origins('*:*') // for latest version
* alone doesn't work which took me down rabbit holes.
I am using v2.1.0 and none of the above answers worked for me.
This did though:
import express from "express";
import http from "http";
const app = express();
const server = http.createServer(app);
const sio = require("socket.io")(server, {
handlePreflightRequest: (req, res) => {
const headers = {
"Access-Control-Allow-Headers": "Content-Type, Authorization",
"Access-Control-Allow-Origin": req.headers.origin, //or the specific origin you want to give access to,
"Access-Control-Allow-Credentials": true
};
res.writeHead(200, headers);
res.end();
}
});
sio.on("connection", () => {
console.log("Connected!");
});
server.listen(3000);
You can try to set origins option on the server side to allow cross-origin requests:
io.set('origins', 'http://yourdomain.com:80');
Here http://yourdomain.com:80 is the origin you want to allow requests from.
You can read more about origins format here
For anyone looking here for new Socket.io (3.x) the migration documents are fairly helpful.
In particular this snippet:
const io = require("socket.io")(httpServer, {
cors: {
origin: "https://example.com",
methods: ["GET", "POST"],
allowedHeaders: ["my-custom-header"],
credentials: true
}
});
If you are getting io.set not a function or io.origins not a function, you can try such notation:
import express from 'express';
import { Server } from 'socket.io';
const app = express();
const server = app.listen(3000);
const io = new Server(server, { cors: { origin: '*' } });
I tried above and nothing worked for me. Following code is from socket.io documentation and it worked.
io.origins((origin, callback) => {
if (origin !== 'https://foo.example.com') {
return callback('origin not allowed', false);
}
callback(null, true);
});
I just wanted to say that after trying a bunch of things, what fixed my CORS problem was simply using an older version of socket.io (version 2.2.0). My package.json file now looks like this:
{
"name": "current-project",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"devStart": "nodemon server.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"socket.io": "^2.2.0"
},
"devDependencies": {
"nodemon": "^1.19.0"
}
}
If you execute npm install with this, you may find that the CORS problem goes away when trying to use socket.io. At least it worked for me.
In my case, I'm using an HTTP server and socket.io
Error:
var http = require('http').Server(app);
var io = require('socket.io')(http);
Solution:
var http = require('http').Server(app);
var io = require('socket.io')(http, { cors: { origin: '*' } });
client:
const socket = io('https://sms-server.cedrick1227.repl.co/', { });
server:
const io = new socket.Server(server, { cors: { origin: '*' } });
it works like a charm for me.
After read a lot of subjetcs on StakOverflow and other forums, I found the working solution for me. This solution is for working without Express.
here are the prerequisites.
call your js script (src=) form the same server the socket will be connected to (not CDN or local call)
ensure to have the same version of socket.io on server and client side
node modules required : fs, path, socket.io and winston for logging
Install Let's encrypt certbot and generate certificate for your domain or buy a SSL certificate
jQuery declared before socket.io.js on client side
UTF-8 encoding
SERVER SIDE
// DEPENDENCIES
var fs = require('fs'),
winston = require('winston'),
path = require('path');
// LOGS
const logger = winston.createLogger({
level : 'info',
format : winston.format.json(),
transports: [
new winston.transports.Console({ level: 'debug' }),
new winston.transports.File({ filename: 'err.log', level: 'err' }),
new winston.transports.File({ filename: 'combined.log' })
]
});
// CONSTANTS
const Port = 9000,
certsPath = '/etc/letsencrypt/live/my.domain.com/';
// STARTING HTTPS SERVER
var server = require('https').createServer({
key: fs.readFileSync(certsPath + 'privkey.pem'),
cert: fs.readFileSync(certsPath + 'cert.pem'),
ca: fs.readFileSync(certsPath + 'chain.pem'),
requestCert: false,
rejectUnauthorized: false
},
(req, res) => {
var filePath = '.' + req.url;
logger.info('FILE ASKED : ' + filePath);
// Default page for visitor calling directly URL
if (filePath == './')
filePath = './index.html';
var extname = path.extname(filePath);
var contentType = 'text/html';
switch (extname) {
case '.js':
contentType = 'text/javascript';
break;
case '.css':
contentType = 'text/css';
break;
case '.json':
contentType = 'application/json';
break;
case '.png':
contentType = 'image/png';
break;
case '.jpg':
contentType = 'image/jpg';
break;
case '.wav':
contentType = 'audio/wav';
break;
}
var headers = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'OPTIONS, POST, GET',
'Access-Control-Max-Age': 2592000, // 30 days
'Content-Type': contentType
};
fs.readFile(filePath, function(err, content) {
if (err) {
if(err.code == 'ENOENT'){
fs.readFile('./errpages/404.html', function(err, content) {
res.writeHead(404, headers);
res.end(content, 'utf-8');
});
}
else {
fs.readFile('./errpages/500.html', function(err, content) {
res.writeHead(500, headers);
res.end(content, 'utf-8');
});
}
}
else {
res.writeHead(200, headers);
res.end(content, 'utf-8');
}
});
if (req.method === 'OPTIONS') {
res.writeHead(204, headers);
res.end();
}
}).listen(port);
//OPENING SOCKET
var io = require('socket.io')(server).on('connection', function(s) {
logger.info("SERVER > Socket opened from client");
//... your code here
});
CLIENT SIDE
<script src="https://my.domain.com:port/js/socket.io.js"></script>
<script>
$(document).ready(function() {
$.socket = io.connect('https://my.domain.com:port', {
secure: true // for SSL
});
//... your code here
});
</script>
This could be a certification issue with Firefox, not necessarily anything wrong with your CORS. Firefox CORS request giving 'Cross-Origin Request Blocked' despite headers
I was running into the same exact issue with Socketio and Nodejs throwing CORS error in Firefox. I had Certs for *.myNodeSite.com, but I was referencing the LAN IP address 192.168.1.10 for Nodejs. (WAN IP address might throw the same error as well.) Since the Cert didn't match the IP address reference, Firefox threw that error.
Alright I had some issues getting this to work using a self signed cert for testing so I am going to copy my setup that worked for me. If your not using a self signed cert you probably wont have these issues, hopefully!
To start off depending on your browser Firefox or Chrome you may have different issues and I'll explain in a minute.
First the Setup:
Client
// May need to load the client script from a Absolute Path
<script src="https://www.YOURDOMAIN.com/node/node_modules/socket.io-client/dist/socket.io.js"></script>
<script>
var options = {
rememberUpgrade:true,
transports: ['websocket'],
secure:true,
rejectUnauthorized: false
}
var socket = io.connect('https://www.YOURDOMAIN.com:PORT', options);
// Rest of your code here
</script>
Server
var fs = require('fs');
var options = {
key: fs.readFileSync('/path/to/your/file.pem'),
cert: fs.readFileSync('/path/to/your/file.crt'),
};
var origins = 'https://www.YOURDOMAIN.com:*';
var app = require('https').createServer(options,function(req,res){
// Set CORS headers
res.setHeader('Access-Control-Allow-Origin', 'https://www.YOURDOMAIN.com:*');
res.setHeader('Access-Control-Request-Method', '*');
res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET');
res.setHeader('Access-Control-Allow-Headers', '*');
if ( req.method === 'OPTIONS' || req.method === 'GET' ) {
res.writeHead(200);
res.end();
return;
}
});
var io = require('socket.io')(app);
app.listen(PORT);
For development the options used on the client side are ok in production you would want the option:
rejectUnauthorized: false
You would more than likely want set to "true"
Next thing is if its a self signed cert you will need to vist your server in a separate page/tab and accept the cert or import it into your browser.
For Firefox I kept getting the error
MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT
The solution for me was to add the following options and accepting the cert in a different page/tab.
{
rejectUnauthorized: false
}
In Chrome I had to open another page and accept the cert but after that everything worked fine with out having to add any options.
Hope this helps.
References:
https://github.com/theturtle32/WebSocket-Node/issues/259
https://github.com/socketio/engine.io-client#methods
I am facing problem while making an chat app using socket.io and node.js & React. Also this issue is not spacefic to Firefox browser, i face same issue in Edge & Chrome also.
"Cross-Origin request is blocked and it is used by some other resources..."
Then i download cors in project directory and put it in the server file index.js as below: To download simply type command using node.js :
npm install cors
const cors = require('cors');
app.use(cors());
This will allow CORS to used by different resources in the files and allow cross origin request in the browser.
For those using socket.io >= v4.4.0
Because I wanted needed the CORS option only for local development, nothing worked here for me.
The solution that I implemented, backend-side :
const io = require("socket.io")(server, {
path: '/api/socket.io',
});
if (process.env.NODE_ENV === 'development') {
io.engine.on('initial_headers', (headers, req) => {
headers['Access-Control-Allow-Origin'] = 'http://localhost:3000';
headers['Access-Control-Allow-Credentials'] = true;
});
io.engine.on('headers', (headers, req) => {
headers['Access-Control-Allow-Origin'] = 'http://localhost:3000';
headers['Access-Control-Allow-Credentials'] = true;
});
}
I was also struggling with this issue until i saw Documentation says: "You can't set 'withCredentials' to true with origin: *, you need to use a specific origin:". So my code looks like this, hope is useful:
WEB CLIENT
const { io } = require("socket.io-client");
const socket = io("localhost:3000", {
extraHeaders: {
"my-custom-header": "abcd"
}
});
SERVER
var express = require('express');
const app = express();
const http = require('http');
const httpServer = http.createServer(app);
const io = require("socket.io")(httpServer, {
cors: {
origin: '*',
methods: ["GET", "POST"],
}
});
Take a look at this:
Complete Example
Server:
let exp = require('express');
let app = exp();
//UPDATE: this is seems to be deprecated
//let io = require('socket.io').listen(app.listen(9009));
//New Syntax:
const io = require('socket.io')(app.listen(9009));
app.all('/', function (request, response, next) {
response.header("Access-Control-Allow-Origin", "*");
response.header("Access-Control-Allow-Headers", "X-Requested-With");
next();
});
Client:
<!--LOAD THIS SCRIPT FROM SOMEWHERE-->
<script src="http://127.0.0.1:9009/socket.io/socket.io.js"></script>
<script>
var socket = io("127.0.0.1:9009/", {
"force new connection": true,
"reconnectionAttempts": "Infinity",
"timeout": 10001,
"transports": ["websocket"]
}
);
</script>
I remember this from the combination of stackoverflow answers many days ago; but I could not find the main links to mention them
Here is the solution from the official documentation:
Since Socket.IO v3, you need to explicitly enable Cross-Origin Resource Sharing (CORS).
const io = require("socket.io")(httpServer, {cors: {
origin: "https://example.com", // or "*"
methods: ["GET", "POST"]}});
The combination that works for me is:
socketio = require('socket.io')(http, {
origins: process.env.WEB_URL, // http(s)://...
cors: {
origin: process.env.WEB_URL,
credentials: true
}
}).listen(process.env.SOCKET_PORT) // 8899
app.set('socketio', socketio)
Use following on the server side:
const express = require("express");
const cors = require("cors");
const http = require("http");
const app = express();
app.use(express.json());
app.use(cors());
const server = http.createServer(app);
const socket = require("socket.io")(server, {
cors: {
origin: "*",
methods: ["GET", "POST"],
},
});
socket.on("connection", (socket) => {
console.log("socket connection : ", socket.id);
});
server.listen(3001, () => {
console.log("server has started!");
});
i simply updated the version of socket.io from 2.x.x to 4.1.2 for backend and did the same ie. updated the version of socket.io-client at frontend from 2.x.x to 4.1.2 ....And it worked
So, basically in v2, the Socket.IO server automatically added the necessary headers to allow Cross-Origin Resource Sharing (CORS) therefor there was no problem for connection between client and server. But this behavior, while convenient, was not great in terms of security, because it meant that all domains were allowed to reach your Socket.IO server.
In v3 and above versions the CORS is disabled by default. Therefor you need to explicitly enable them on your server side script.
Example of my code:
In v2 of socket.io the server script looked like :
const io = require('socket.io')(8000);
But in v3 and above versions this code becomes to :
const io = require('socket.io')(8000, {
cors: {
origin: ['http://localhost:5500'],
},
});
// Remember by setting cors you allow you client to communicate with the socket server
// In this case 8000 is my port on which my socket connection is running and 5500 is my port where my client files are hosted.
// Socket connection runs on a different port and your client files on different
// Also you need to install socket.io-client where you have installed your socket.io modules
For more clarification I'm adding my files
This is my HTML File :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="http://localhost:8000/socket.io/socket.io.js"" content="text/javascript"></script>
<script src="javascript/client.js"></script>
<link rel="stylesheet" href="css/style.css">
<title>Chat App</title>
</head>
<body>
</body>
</html>
Here is my javascript/client.js
const socket = io('http://localhost:8000/');
And this is server/server.js
const io = require('socket.io')(8000, {
cors: {
origin: ['http://localhost:5500'],
},
});
io.on('connection', socket =>{
console.log(socket.id);
});
// If you still can't get it more detailed information can be seen on https://socket.io/docs/v4/migrating-from-2-x-to-3-0/#CORS-handling
// Also a video from which i got this solution https://youtu.be/ZKEqqIO7n-k
I had the same problem and any solution worked for me.
The cause was I am using allowRequest to accept or reject the connection using a token I pass in a query parameter.
I have a typo in the query parameter name in the client side, so the connection was always rejected, but the browser complained about cors...
As soon as I fixed the typo, it started working as expected, and I don't need to use anything extra, the global express cors settings is enough.
So, if anything is working for you, and you are using allowRequest, check that this function is working properly, because the errors it throws shows up as cors errors in the browser. Unless you add there the cors headers manually when you want to reject the connection, I guess.
Using same version for both socket.io and socket.io-client fixed my issue.
Sometimes this issue is faced when the node server stoped.
So, check if your node server working ok.
Then you can use
io.set('origins', 'http://yourdomain.com:PORT_NUMBER');
I used version 2.4.0 of socket.io in easyRTC and used the following code in server_ssl.js which worked for me
io = require("socket.io")(webServer, {
handlePreflightRequest: (req, res) => {
res.writeHead(200, {
"Access-Control-Allow-Origin": req.headers.origin,
"Access-Control-Allow-Methods": "GET,POST,OPTIONS",
"Access-Control-Allow-Headers": "Origin, X-Requested-With, Content-Type, Accept, Referer, User-Agent, Host, Authorization",
"Access-Control-Allow-Credentials": true,
"Access-Control-Max-Age":86400
});
res.end();
}
});
If you get socket.io app working on Chrome, Safari and other browsers but you still encounter CORS issues in Firefox, and you are using a self-signed certificate, then the problem is that Firefox does not accept self-signed certificates by default, and you have to add an exception by going to Firefox's Preferences > Certificates > View Certificates > Add Exception.
If you don't do this, then Firefox shows the error you posted which is misleading, but deep within its Developer Tools, you will find this error: MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT. This indicates that Firefox is not accepting the certificate at all because it is self-signed.
const options = {
cors: {
origin:
String(process.env.ORIGINS_STRING) === "ALL"
? true
: String(process.env.ORIGINS_STRING).split(","),
methods: ["GET", "PUT", "POST", "DELETE"],
allowedHeaders: [
"Access-Control-Allow-Headers",
"X-Requested-With",
"X-Access-Token",
"Content-Type",
"Host",
"Accept",
"Connection",
"Cache-Control",
],
credentials: true,
optionsSuccessStatus: 200,
},
};
in .env file :
ORIGINS_STRING=ALL
or
ORIGINS_STRING=http://localhost:8080,http://localhost:8081
I was working with socket.io: 4.2.x, node: 14.17.x & #hapi/hapi: 20.1.x.
After trying multiple ways as mentioned in other answers, I found that the only working solutions for these version is:
const io = require('socket.io')(server.listener, { cors: { origin: '*' } });
Please make sure you have { cors: { origin: '*' } } in the options object.
I am using SocketIO with implicit http server and I am using v4.4 of socket io, I had to do it like this in the server:
const { Server } = require("socket.io");
const io = new Server(PORT, {})
io.engine.on("headers", (headers, req) => {
headers["Access-Control-Allow-Origin"] = "http://yourdomain.com"
headers["Access-Control-Allow-Headers"] = "origin, x-requested-with, content-type"
headers["Access-Control-Allow-Methodsn"] = "PUT, GET, POST, DELETE, OPTIONS"
})
const io = require('socket.io')(server, {
cors: {
origin: ['https://example.com','http://example.com','ip-address'],
}
});
Dont use origin: '*' it is a big security mistake!
origin can be used like an array with diffrent entry types:
URI with protocols like http/https
IP Address
Environment variables like process.env.WEB_URL

Express + Passport + CORS: session allowed for multiple domains

I am trying to make the frontend (React JS) work with my backend server (Express JS). I am still fighting with CORS. The frontend requests are still blocked by CORS.
According to CORS documentation I have set my Express instance to use cors() as middleware:
const app = express();
// Middlewares
const whitelist = [
'http://localhost:3000',
'http://localhost:3001'
];
const corsOptions = {
origin: function (origin, callback) {
if (whitelist.indexOf(origin) !== -1) {
callback(null, true);
} else {
callback(new Error('Not allowed by CORS'));
}
}
};
app.use(cors(corsOptions));
If someone asks why am I using CORS with localhost at all, is because I was told to do so since I had to send withCredentials: true header from axios requests to persist session after login.
I just added axios.defaults.withCredentials = true to intercept requests in the frontend.
The way it was working before adding more domains to corsOptions was setting up a middlewares to let the server work with the frontend:
export const setHeaders = (req, res, next) => {
res.header('Access-Control-Allow-Origin', process.env.APP_URL);
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
next();
};
...
app.use(setHeaders);
If I remove the previous code, it won't work even for one domain.
So, what I have to change in order to let the server fetch data from multiple domains? Thanks in advance.
Add credentials and allowedHeaders options to your corsOptions config
credentials: true,
allowedHeaders: ['Origin, X-Requested-With, Content-Type, Accept'],
Read https://www.npmjs.com/package/cors#configuration-options
Also, you can whitelist domains with 127.0.0.1 as you might want to access them via localhost or 127.0.0.1
Full code
const app = express();
// Middlewares
const whitelist = [
'http://localhost:3000',
'http://127.0.0.1:3000'.
'http://localhost:3001',
'http://127.0.0.1:3001',
];
const corsOptions = {
credentials: true,
allowedHeaders: ['Origin, X-Requested-With, Content-Type, Accept'],
origin: function (origin, callback) {
if (whitelist.indexOf(origin) !== -1) {
callback(null, true);
} else {
callback(new Error('Not allowed by CORS'));
}
}
};
app.use(cors(corsOptions));

installing Socket.IO on NodeJs server

I would use Socket.IO . I have read the official documentation and tried to do the same thing so I create my server :
// server.js
// BASE SETUP
// =============================================================================
// call the packages we need
var express = require("express"); // call express
var app = express();
var bodyParser = require("body-parser");
// define our app using express
var routerProj = require("./routes/ajoutProj");
var mongoose = require("mongoose");
mongoose.Promise = global.Promise;
mongoose.connect("mongodb://localhost:27017", {
useMongoClient: true
/* other options */
}); // connect to our database
mongoose.connection.on("error", function(error) {
console.log("error", error);
});
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET, POST, PUT ,DELETE");
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept"
);
next();
});
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use("/api/proj", routerProj);
app.get("/", function(req, res) {
res.sendFile(__dirname + "../src/index.html");
});
// Chargement de socket.io
// Quand un client se connecte, on le note dans la console
io.sockets.on("connection", function(socket) {
console.log("User is coonected!");
});
var port = process.env.PORT || 8081; // set our port
// START THE SERVER
// =============================================================================
var server = app.listen(port);
var io = require("socket.io").listen(server);
My angular index.htlm file is in this path relatively to server.js : ../src/app/index.html
When I restart server and angular app, then open new window I don't have a message on the servers's console telling me that a user is connected knowing that angular is making calls to the server api
I don't know where is the problem
Update
I have added socket.IO on client side
import { Injectable } from "#angular/core";
import { NouveauProjet } from "./models/nouveau-projet";
import { HttpClient, HttpResponse } from "#angular/common/http";
import { Observable } from "rxjs/Observable";
import "rxjs/add/operator/map";
import "rxjs/add/operator/catch";
import * as io from "socket.io-client";
#Injectable()
export class AjoutprojService {
apiURL = "http://127.0.0.1:8080/api/proj/projets";
private socket = io("http://localhost:8081");
constructor(private http: HttpClient) {}
getAllProj(): Observable<NouveauProjet[]> {
return this.http.get<NouveauProjet[]>(
"http://127.0.0.1:8081/api/proj/projets"
);
}
getProj(id): Observable<NouveauProjet[]> {
return this.http.get<NouveauProjet[]>(
"http://127.0.0.1:8081/api/proj/nouvProjs/${id}"
);
}
addProj(nouveauProjet: NouveauProjet): Observable<any> {
return this.http.post<NouveauProjet[]>(
"http://127.0.0.1:8081/api/proj/projets",
nouveauProjet
);
}
}
/* private handleError ( response: HttpResponse): Observable<any> {
let errorMessage= `${response.status} - ${response.statusText}`;
return Observable.throw(errorMessage);
}*/
Restarted server , client , no result
Update 2
after adding socket.on('event', function(evt){ console.log(evt); });I get those errors :
Failed to load http://localhost:8081/socket.io/?EIO=3&transport=polling&t=M2tXQXh: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. Origin 'http://localhost:4200' is therefore not allowed access. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
GET http://localhost:8081/socket.io/?EIO=3&transport=polling&t=M2tXQXh 404 (Not Found)
If I set res.header("Access-Control-Allow-Origin", "*"); To res.header("Access-Control-Allow-Origin", "http://localhost:4200");
I get this error
Failed to load http://localhost:8081/socket.io/?EIO=3&transport=polling&t=M2uichH: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'. Origin 'http://localhost:4200' is therefore not allowed access. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
I notice a difference in the error . Here The value of the 'Access-Control-Allow-Credentials' header in the response is ''
When I put localhost:8081 : The value of the 'Access-Control-Allow-Credentials' header in the response is 'localhost:8081'
Based on the error, I suspect the problem is that you are using a wildcard in your server's CORS response header:
res.header("Access-Control-Allow-Origin", "*");
Why is this a problem? From the docs:
When responding to a credentialed request, the server must specify an origin in the value of the Access-Control-Allow-Origin header, instead of specifying the "*" wildcard.
Here is a relevant StackOverflow answer:
This is a part of security, you cannot do that. If you want to allow credentials then your Access-Control-Allow-Origin must not use *. You will have to specify the exact protocol + domain + port.

Unable to use 3rd party APIs getting error as No 'Access-Control-Allow-Origin' header is present on the requested resource

I am trying to hit 3rd party api using angularjs as shown below
Only in chrome I was able to see this issue and IE works perfectly
I got the error as...
XMLHttpRequest cannot load https://api.forecast.io/forecast/2c56930e3e0117b9943b9f618acfe981/17.3434321,78.536526. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.
:3000/#/home:1 XMLHttpRequest cannot load https://www.w3schools.com/angular/customers.php. 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:3000' is therefore not allowed access.
homeController.js:23 failure
:3000/#/home:1 XMLHttpRequest cannot load http://www.w3schools.com/angular/customers.php. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.
Angular JS code is:
angular.module('homeModule', []).
controller('HomeCtrl', ['$scope','$http'
, function($scope,$http ){
$http.get("http://www.w3schools.com/angular/customers.php").then(function (response) {
$scope.test1 = response.data.records;
});
$http.get("https://api.forecast.io/forecast/2c56930e3e0117b9943b9f618acfe981/17.3434321,78.536526").then(function (response) {
$scope.test2 = response;
});
$http({
method: 'GET',
url: "https://www.w3schools.com/angular/customers.php",
headers: {
'Access-Control-Allow-Origin': '*'
}
}).
success(function(status) {
$scope.test3 = response;
}).
error(function(status) {
console.log("failure");
});
}])
and My server.js is
var express = require('express'),
http = require('http');
var app = express();
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.use(express.static(__dirname + '/public'))
.use('/node_modules', express.static(__dirname + '/node_modules'));
http.createServer(app).listen(3000, function () {
console.log("Server ready at http://localhost:3000");
});
First thing, you're requesting data from 3rd party servers. NOT your server. So setting headers and access control information on your server is not going to change anything.
The only workaround you can use here is to use padded JSON.
In angular, you'll need to use $http.jsonp and not $http.get.
Change your code to
$http.jsonp("http://www.w3schools.com/angular/customers.php").then(function (response) {
$scope.test1 = response.data.records;
});
$http.jsonp("https://api.forecast.io/forecast/2c56930e3e0117b9943b9f618acfe981/17.3434321,78.536526").then(function (response) {
$scope.test2 = response;
});
EDIT:
Forgot to mention callback setting in case of JSONP requests.
You'll need to specify a callback parameter as ?callback=JSON_CALLBACK in your URLs.
Change your code to
$http.jsonp("http://www.w3schools.com/angular/customers.php?callback=JSON_CALLBACK").then(function (response) {
$scope.test1 = response.data.records;
});
$http.jsonp("https://api.forecast.io/forecast/2c56930e3e0117b9943b9f618acfe981/17.3434321,78.536526?callback=JSON_CALLBACK").then(function (response) {
$scope.test2 = response;
});
And it should work.
EDIT 2:
As per the suggestion from avck, the above method is not only bad but also it involves security risks.
The right way to do this is as follows.
You're gonna have to change YOUR server.
First do,
npm install request
Then in your server.js
var express = require('express'),
http = require('http'),
request = require('request');
var app = express();
/* This is not needed
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.get('/getDataFromW3Schools', function(req, res, next){
var url = 'http://www.w3schools.com/angular/customers.php';
request(url, function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body);
res.json(body);
}
});
});
app.get('/getDataFromForecast', function(req, res, next){
var url = 'https://api.forecast.io/forecast/2c56930e3e0117b9943b9f618acfe981/17.3434321,78.536526';
request(url, function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body);
res.json(body);
}
});
});
app.use(express.static(__dirname + '/public')).use('/node_modules', express.static(__dirname + '/node_modules'));
http.createServer(app).listen(3000, function () {
console.log("Server ready at http://localhost:3000");
});
And in your client side, you'll have to do,
$http.get("/getDataFromW3Schools").then(function (response) {
$scope.test1 = response.data.records;
});
$http.get("/getDataFromForecast").then(function (response) {
$scope.test2 = response;
});
PLEASE NOTE: Now we're using $http.get.

Making CORS Request in Node.js/Express and AngularJS

I have seen many answers in stack overflow which says setting response headers will make you "CORS" request.But no solution worked for me.I have written the following code:
//Server.js Code
var express = require('express'),
app = express();
app.all('*',function(req, res, next) {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.setHeader('Access-Control-Allow-Credentials', true);
res.setHeader('Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, OPTIONS');
next();
I am trying to access the content from the URL using $http in client side:
//Controller.js
$http.get('http://domainA.com/a/ipadapi.php?id=135&client=ipad').success(function(response){
alert("I got response");
});
It's showing the following error in console.
XMLHttpRequest cannot load http://domainA.com/a/ipadapi.php?id=135&client=ipad The 'Access-Control-Allow-Origin' header has a value 'http://example.xxxxx.com' that is not equal to the supplied origin. Origin 'http://localhost:3000' is therefore not allowed access.
Note:I am new to nodeJS,Express and AngularJs
When you are passing credentials with CORS, you need to lock down the accepted origins. Try changing your origins from * to "localhost:3000"
See cross origin resource sharing with credentials
Change the header info from
res.setHeader("Access-Control-Allow-Origin", "*");
TO
res.header('Access-Control-Allow-Origin', 'http://localhost:3000');
If you're not the owner of domainA then you cannot send CORS headers from that domain. You can use your Node server as middleware, and proxy the request from your server to domainA. Your server can send CORS headers back to your angular app. pseudo code with hapi and needle:
import Hapi from 'hapi'
import needle from 'needle'
const server = new Hapi.Server()
server.connection({
port: 9090
, routes: {
cors: true
}
})
const handler = (req, reply) => {
const url = 'https://domainA.com'
, data = {
body: 'code'
}
needle.post(url, 'body=${data.body}', function(err, res) {
let json = JSON.parse(res.body)
reply(json.data)
})
}
server.route({
method: 'GET',
path: '/route/{id}',
handler: handler
}
)
server.start( err => {
if( err ) {
console.error( 'Error was handled!' )
console.error( err )
}
console.log( 'Server started at ${ server.info.uri }' )
})

Categories