Wandrille Wandrille - 3 months ago 39
HTTP Question

No 'Access-Control-Allow-Origin' header with ExpressJS to local server

I know that this subject seems to be already answered many time but i really don't understand it.


  • I have an local angular-fullstack app (Express, NodeJs) which has his
    server A (localhost:9000/).

  • i have an another local front app B (BlurAdmin done with
    generator-gulp-angular) (localhost:3000/)



My server A was autogenerate with Express and Nodejs:

app.use(function (req, res, next) {

res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', false);
next();
});


In my app B, a GET request to my API of serveur A works

$http.get('http://localhost:9000/api/shows')


But with a PUT request:

$http.put('http://localhost:9000/api/shows/1', object)


i have the following error:


XMLHttpRequest cannot load http://localhost:9000/api/shows/1. No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:3000' is therefore not allowed
access. The response had HTTP status code 403.


I try with:

$http({
method: "PUT",
url:'http://localhost:9000/api/shows/1',
headers: {
'Content-type': 'application/json'
},
data:object
});


Not working,

I try with:

res.header('Access-Control-Allow-Origin', '*');


Not working,

I have installed *ExtensionAllow-Control-Allow-Origin: ** for chrome and that has done nothing (that return just not all the code but only error 403 (forbidden)

I don't really know why this is not working for PUT when it's working with GET.

Have you already had this problem? Thanks!

Updated:1 The result in my Browser:
for GET

General:
Request URL:http://localhost:9000/api/shows/1
Request Method:OPTIONS
Status Code:200 OK

Request header:
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4,de-DE;q=0.2,de;q=0.2
Access-Control-Request-Headers:content-type
Access-Control-Request-Method:PUT
Connection:keep-alive
Host:localhost:9000
Origin:http://localhost:3000
Referer:http://localhost:3000/

Response header:
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:X-Requested-With,content-type
Access-Control-Allow-Methods:GET, POST, OPTIONS, PUT, PATCH, DELETE
Access-Control-Allow-Origin:http://localhost:3000
Allow:GET,HEAD,PUT,PATCH,DELETE
Connection:keep-alive
Content-Length:25
Content-Type:text/html; charset=utf-8


For PUT request:

general:
Request URL:http://localhost:9000/api/shows/1
Request Method:PUT
Status Code:403 Forbidden

Response Header:
Connection:keep-alive
Content-Encoding:gzip
Content-Type:application/json; charset=utf-8
Date:Thu, 25 Aug 2016 16:29:44 GMT
set-cookie:connect.sid=s%3AsVwxxbO-rwLH-1IBZdFzZK1xTStkDUdw.xuvw41CVkFCRK2lHNlowAP9vYMUwoRfHtc4KiLqwlJk; Path=/; HttpOnly
set-cookie:XSRF-TOKEN=toaMLibU5zWu2CK19Dfi5W0k4k%2Fz7PYY%2B9Yeo%3D; Path=/
Strict-Transport-Security:max-age=31536000; includeSubDomains; preload

Request header:
Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4,de-DE;q=0.2,de;q=0.2
Connection:keep-alive
Content-Length:27
Content-Type:application/json
Host:localhost:9000
Origin:http://localhost:3000
Referer:http://localhost:3000/

Request Payload:
{url_name: "myData"}
url_name
:
"myData"


Thanks for helping

Update 2: with https://github.com/troygoode/node-cors-server/blob/master/app.js and the work of @Chris Foster
I have install
npm cors --save

in my app.js,
i have now the following code:

import express from 'express';
import cors from 'cors';

var app = express()

var corsOptions = {
origin: 'http://localhost:3000'
}
var issuesoption = {
origin: true,
methods: ['PUT'],
credentials: true,
};


app.use(cors(corsOptions))
app.options('*', cors(issuesoption));
app.put('/api/shows/:id',cors(issuesoption) ,function(req,res){
res.json({
data: 'Issue #2 is fixed.'
});
});


And that is still not working with:

$http.put("http://localhost:9000/api/shows/1",object)


BUT i don't have any 403 error, I have now,

Request URL:http://localhost:9000/api/shows/1
Request Method:PUT
Status Code:200 OK


But that doesn't put the data into the server and i have in Preview:

{data: "Issue #2 is fixed."}

Answer

When you make a request that can change something (POST, PUT, etc), CORS rules require that the browser makes a preflight request (OPTIONS) before making the actual request.

In Node, you have to specifically handle these OPTION requests. It's likely you are only handling the PUT (app.put('/etc/etc/')), and the preflight request is failing.

You need to add handling for preflight OPTION requests, but better yet check out the cors package which makes this all much more simple and does it for you:

const express = require('express')
const cors = require('cors')

const app = express()

const corsOptions = {
  origin: 'http://example.com'
}

app.use(cors(corsOptions))