I'm developing a server at Node js and my front-end at Angularjs, but I'm getting an error when I try to make a request from my front-end:
XMLHttpRequest cannot load http://localhost:8085/server/authenticate/.
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:9000' is therefore not allowed
access.
My code at my server.js
app.use(function(req,res,next){
res.setHeader('Access-Control-Allow-Oringin','*');
res.setHeader('Access-Control-Allow-Methods','GET,POST,OPTIONS');
res.setHeader('Access-Control-Allow-Headers','X-Requested-With,content-type,Authorization,accept');
if (req.method === 'OPTIONS'){
res.statusCode = 200;
return res.end();
}
else{
return next();
}
});
Any suggestions?
NOTE: back-end and front-end are not at the same port, I'm trying to make it work as a CROSS-Origin resourse.
var express = require('express')
, cors = require('cors')
, app = express();
app.use(cors());
/* Make your app with CORS support: for more information: https://www.npmjs.com/package/cors*/
There is a little error in your header name Access-Control-Allow-Oringin
Try this
app.use(function(req,res,next){
res.setHeader('Access-Control-Allow-Origin','*');
res.setHeader('Access-Control-Allow-Methods','GET,POST,OPTIONS');
res.setHeader('Access-Control-Allow-Headers','X-Requested-With,content-type,Authorization,accept');
if (req.method === 'OPTIONS'){
res.statusCode = 200;
return res.end();
}
else{
return next();
}
});
Related
I'm running one client local server with "VSC's Live servers" on localhost:5500, and I'm running a remote server using heroku.
Here is the relevant code regarding the AJAX call client-side when submitting a form:
const xhr = new XMLHttpRequest();
xhr.open("POST", "https://git.heroku.com/morning-falls-52888.git");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(JContactRequest);
xhr.onload = () => {
const status = xhr.status;
if (status >= 200 && status < 300 ) {
$("form").append("<p id='submit-message' style='text-align:center;'>Thank you for your submission!</p>");
} else if (status == 418 ) {
window.alert(`Error: ${xhr.status}\nCannot brew coffee, I am a teapot.`);
} else {
console.log(`Before append ${status} ready state: ${xhr.readystate}`);
$("form").append("<p id='submit-message' style='text-align:center;'>Submission Failed</p>");
console.log(`After append ${status} ready state: ${xhr.readystate}`);
}
}
And here is the code server side:
require('dotenv').config();
const express = require('express');
const app = express();
app.use(express.json());
const PORT = process.env.PORT ||4500;
const cors = require("cors");
app.use(cors());
app.listen(PORT, () => { console.log(`Listening on PORT: ${PORT}`) });
// app.use((req,res,next)=>{
// res.status(404).send('this is working');
// })
app.get('/', (req, res) => {
res.header("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,OPTIONS");
res.status(201).send();
console.log("received get request");
})
app.post('/', (req, res) => {
var body=req.body;
console.log(body);
for(let [key,value] of Object.entries(body)){
if(value==""){
res.status(400).send(`Empty Field in ${key}`);
res.end();
break;
}
}
var email = body.emailfield;
if (body.comment == "Can you brew coffee?") {
res.status(418).send();
} else {
res.status(200).send('message sent');
}
// calling the api
const sgMail = require('#sendgrid/mail');
sgMail.setApiKey(process.env.SENDGRID_API_KEY);
const msg = {
to: email,
from: 'd#gmail.com', // Use the email address or domain you verified above
templateId:'*************************************',
dynamic_template_data:body,
}
//ES6
sgMail
.send(msg)
.then(() => {}, error => {
console.error(error);
if (error.response) {
console.error(error.response.body)
console.log(process.env.SENDGRID_API_KEY)
}
});
});
The message I'm getting on my console is the following:
Access to XMLHttpRequest at 'https://git.heroku.com/morning-falls-52888.git' from origin 'http://127.0.0.1:5500' 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.
I'm kind of stumped because I would have thought that app.use(cors()) would have access-control-allow-origin=*.
I'm still very new to this, so any help is mighty appreciated. Thanks!
EDIT I just wanted to add that this code was running fine when I was running the server locally on port 4500
xhr.open("POST", "https://git.heroku.com/morning-falls-52888.git");
You're making an HTTP request to Heroku's Git repo, not to your application running on Heroku (which will have a URL like https://APPLICATION_NAME.herokuapp.com/something)
The CORS permissions have to be granted for the URL you are making the request to, not one that is loosely adjacent to it.
I am trying to send a new membership from a form in react to my express server to add to the mailchimp memberlist I am getting a cors error and I don't know if I am missing any proxys. I want a user to be able to sign up in react and then it sends it to the mailchimp database
I have been able to get the members list but I am not allowed to post to it :
This is my express backend :
const express = require('express');
const Mailchimp = require('mailchimp-api-v3');
require('dotenv').config();
var request = require('superagent');
var mc_api_key = process.env.REACT_APP_MAILCHIMP_API;
var list_id = process.env.REACT_APP_LIST_ID;
const app = express();
const mailchimp = new Mailchimp(mc_api_key);
const port = process.env.PORT || 5000;
// console.log that your server is up and running
app.listen(port, () => console.log(`Listening on port ${port}`));
app.use((request, response, next) => {
response.header("Access-Control-Allow-Origin", "*");
response.header("Access-Control-Allow-Headers", "Content-Type");
next();
});
// Routes
app.post('/signup', function (req, res) {
request
.post('https://' + 'us20' + '.api.mailchimp.com/3.0/lists/' + list_id + '/members/')
.set('Content-Type', 'application/json;charset=utf-8')
.set('Authorization', 'Basic ' + new Buffer('any:' + mc_api_key ).toString('base64'))
.send({
'email_address': req.body.email,
'status': 'subscribed',
'merge_fields': {
'FNAME': req.body.firstName,
'LNAME': req.body.lastName
}
})
.end(function(err, response) {
if (response.status < 300 || (response.status === 400 && response.body.title === "Member Exists")) {
res.send('Signed Up!');
} else {
res.send('Sign Up Failed :(');
}
});
});
This is where I am trying to fetch in react in my app.js file :
onSubmit = (e,email) => {
e.preventDefault()
this.setState({user:email})
fetch('http://localhost:5000/signup',{
method: 'POST',
headers: {
'Accept':'application/json',
'Content-type':'application/json'
},
body: JSON.stringify({email_address: email, status: 'subscribed'})
}).then(console.log)
};
when clicking submit I expect the members email address to be sent over to the mailchimp API instead I am getting this error :
Access to fetch at 'http://localhost:5000/signup' 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.
Try this.
app.use((request, response, next) => {
response.header("Access-Control-Allow-Origin", "*");
response.header("Access-Control-Allow-Headers", "Content-Type");
next();
});
to
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "http://localhost:5000");
next();
});
Just enable CORS on your server.
Install cors
$ npm install --save cors
Enable cors in express:
const cors = require('cors');
const express = require('express');
const app = express();
app.use(cors());
More about cors here.
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.
I am trying to learn socket.io from this tutorial here. But the problem is I can't make the app run. This is the error I am getting:
XMLHttpRequest cannot load
http://127.0.0.1:3000/socket.io/?EIO=3&transport=polling&t=LZFI7Tq. No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost' is therefore not allowed access.
The response had HTTP status code 404.
This is the server side connection
var io = require('socket.io');
var socket = io.listen(3000, '127.0.0.1');
// all the people that have joined the chat
var people = {};
socket.on('connection', function (client) {
console.log('An user connected');
client.on('join', function(name) {
people[client.id] = name;
// client.emit() will only update the client that you are looking
// at, whereas socket.sockets.emti() will update all connected clients
client.emit('update', 'You have successfully connected..');
socket.sockets.emit('update', name + " has joined the conversation..");
socket.sockets.emit('update-people', people);
});
client.on('send', function(msg){
socket.sockets.emit('chat', people[client.id], msg);
});
client.on('disconnect', function() {
socket.sockets.emit('update', people[client.id] + ' has left the conversation..');
delete people[client.id];
socket.sockets.emit('update-people', people);
});
});
And this is the client side connection
var socket = io.connect('http://127.0.0.1:3000');
I have gone through several posts related to this issue but cant solve it. Please help me.
Add this middle-ware on the server where your cookies are created
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-Type');
res.header('Access-Control-Allow-Credentials', 'true');
next();
})
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 }' )
})