Pas de 'Access-Control-Allow-Origin' - Problème de port Node / Apache

260

j'ai créé une petite API en utilisant Node / Express et en essayant d'extraire des données en utilisant Angularjs mais comme ma page html fonctionne sous apache sur localhost: 8888 et que l'API du nœud est à l'écoute sur le port 3000, je reçois le No 'Access-Control- Autoriser l'origine ». J'ai essayé d'utiliser node-http-proxyet Vhosts Apache mais sans grand succès, veuillez voir l'erreur complète et le code ci-dessous.

XMLHttpRequest ne peut pas charger localhost: 3000. Aucun en-tête «Access-Control-Allow-Origin» n'est présent sur la ressource demandée. L'origine 'localhost: 8888' n'est donc pas autorisée à accéder. "

// Api Using Node/Express    
var express = require('express');
var app = express();
var contractors = [
    {   
     "id": "1", 
        "name": "Joe Blogg",
        "Weeks": 3,
        "Photo": "1.png"
    }
];

app.use(express.bodyParser());

app.get('/', function(req, res) {
  res.json(contractors);
});
app.listen(process.env.PORT || 3000);
console.log('Server is running on Port 3000')

Code angulaire

angular.module('contractorsApp', [])
.controller('ContractorsCtrl', function($scope, $http,$routeParams) {

   $http.get('localhost:3000').then(function(response) {
       var data = response.data;
       $scope.contractors = data;
   })

HTML

<body ng-app="contractorsApp">
    <div ng-controller="ContractorsCtrl"> 
        <ul>
            <li ng-repeat="person in contractors">{{person.name}}</li>
        </ul>
    </div>
</body>
user1336103
la source

Réponses:

622

Essayez d'ajouter le middleware suivant à votre application NodeJS / Express (j'ai ajouté quelques commentaires pour votre commodité):

// Add headers
app.use(function (req, res, next) {

    // Website you wish to allow to connect
    res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8888');

    // Request methods you wish to allow
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');

    // Request headers you wish to allow
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');

    // Set to true if you need the website to include cookies in the requests sent
    // to the API (e.g. in case you use sessions)
    res.setHeader('Access-Control-Allow-Credentials', true);

    // Pass to next layer of middleware
    next();
});

J'espère que cela pourra aider!

jvandemo
la source
2
Pouvez-vous aider à spécifier exactement où cela va? J'ai le code suivant sur mon serveur. Est-ce que ça va juste après ça? var app = require ('express') (), server = require ('http'). createServer (app), io = require ('socket.io'). listen (server), request = require ("request") , url = require ("url"); server.listen (6969); // ça va ici? sur une nouvelle ligne?
Art Geigel
1
@jvandemo dois-je changer l'app.get ('/', fonction (req, res) en ... fonction (req, res, suivante)?
Sangram Singh
10
Tu es ma personne préférée en ce moment. Je vous remercie. Pouvons-nous ajouter une note que ce code doit se produire avant que les routes ne soient définies pour les noobs comme moi?
gegillam
1
Comment faire fonctionner cela en utilisant le module de demande?
Rohit Tigga
2
Cela n'a pas fonctionné dans mon cas. Toujours obtenir cette erreur: «La réponse à la demande de contrôle en amont ne passe pas la vérification du contrôle d'accès: aucun en-tête« Access-Control-Allow-Origin »n'est présent sur la ressource demandée. L'origine« abc.xyz.net:212 »n'est donc pas autorisée accès. La réponse avait le code d'état HTTP 500. "
user1451111
96

La réponse acceptée est correcte, si vous préférez quelque chose de plus court, vous pouvez utiliser un plugin appelé cors disponible pour Express.js

C'est simple à utiliser, pour ce cas particulier:

var cors = require('cors');

// use it before all route definitions
app.use(cors({origin: 'http://localhost:8888'}));
Fabiano Soriani
la source
3
J'ai dû m'en servir {origin: 'null'}pour que ça marche ... Apparemment, mon navigateur envoie nullcomme origine?
Ricardo Cruz
2
Pourquoi réinventer la roue. Je suis toujours pour une solution packagée par rapport à l'extrait de code
Pierre
douce petite bibliothèque qui a géré mon cas d'utilisation de vouloir très bien différentes méthodes d'origines différentes ... et moins de fatigue de code pour le prochain gars qui le regarde.
Kyle Baker
6
Merci, a app.use(cors({origin: '*'}));travaillé pour moi, selon les enable-cors .
danialk
2
Je suggère de consulter la page npm cors pour en faire un meilleur usage. Cela a rendu les choses très claires pour moi =).
13013SwagR
30

Une autre façon consiste simplement à ajouter les en-têtes à votre itinéraire:

router.get('/', function(req, res) {
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE'); // If needed
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type'); // If needed
    res.setHeader('Access-Control-Allow-Credentials', true); // If needed

    res.send('cors problem fixed:)');
});
Asaf Hananel
la source
8
)de smiley m'a confondu
diEcho
17

La meilleure réponse a bien fonctionné pour moi, sauf que je devais mettre en liste blanche plus d'un domaine.

De plus, la première réponse souffre du fait que la OPTIONSdemande n'est pas gérée par le middleware et que vous ne l'obtenez pas automatiquement.

Je stocke les domaines en liste blanche comme allowed_originsdans la configuration Express et je mets le domaine correct en fonction de l'en- origintête car Access-Control-Allow-Originil ne permet pas de spécifier plus d'un domaine.

Voici ce que j'ai fini avec:

var _ = require('underscore');

function allowCrossDomain(req, res, next) {
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');

  var origin = req.headers.origin;
  if (_.contains(app.get('allowed_origins'), origin)) {
    res.setHeader('Access-Control-Allow-Origin', origin);
  }

  if (req.method === 'OPTIONS') {
    res.send(200);
  } else {
    next();
  }
}

app.configure(function () {
  app.use(express.logger());
  app.use(express.bodyParser());
  app.use(allowCrossDomain);
});
Dan Abramov
la source
Est-ce le même 'if (app.get (' origines autorisées '). IndexOf (origine)! == - 1)?'?
Rune Jeppesen
13

Le code de réponse ne permet qu'à localhost: 8888. Ce code ne peut pas être déployé sur la production ou sur un autre nom de serveur et de port.

Pour le faire fonctionner pour toutes les sources, utilisez plutôt ceci:

// Add headers
app.use(function (req, res, next) {

    // Website you wish to allow to connect
    res.setHeader('Access-Control-Allow-Origin', '*');

    // Request methods you wish to allow
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');

    // Request headers you wish to allow
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');

    // Set to true if you need the website to include cookies in the requests sent
    // to the API (e.g. in case you use sessions)
    res.setHeader('Access-Control-Allow-Credentials', true);

    // Pass to next layer of middleware
    next();
});
Vicheanak
la source
2
Cela ne fonctionne pas pour moi! "* n'est pas une origine valide". Il semble que le caractère * ne soit pas reconnu comme caractère générique.
Francesco
Ça marche pour moi. c'est-à-dire en utilisant le joker '*' fonctionne à la fois pour le chrome et le safari.
AnBisw
Merci;) Fonctionne bien
Mauro
9

Installez la dépendance cors dans votre projet:

npm i --save cors

Ajoutez à votre fichier de configuration de serveur les éléments suivants:

var cors = require('cors');
app.use(cors());

Cela fonctionne pour moi avec la version 2.8.4 cors.

monikaja
la source
"cors": "^2.8.5", "express": "^4.16.3",fonctionne très bien avec la ligne suggérée par @monikaja. Merci!
RamiroIsBack
Cela permet à toutes les origines / domaines d'accéder à l'application, ce que vous ne voulez généralement pas faire. À la place, spécifiez uniquement les domaines autorisés.
Lacho Tomov
7

Cela a fonctionné pour moi.

app.get('/', function (req, res) {

    res.header("Access-Control-Allow-Origin", "*");
    res.send('hello world')
})

Vous pouvez modifier * pour répondre à vos besoins. J'espère que cela peut vous aider.

dmx
la source
7

Salut, cela se produit lorsque le frontal et le backend s'exécutent sur des ports différents. Le navigateur bloque les réponses du backend en raison de l'absence sur les en-têtes CORS. La solution est de faire ajouter les en-têtes CORS dans la requête backend. La manière la plus simple est d'utiliser le paquetage cors npm.

var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())

Cela permettra aux en-têtes CORS dans toutes vos demandes. Pour plus d'informations, vous pouvez vous référer à la documentation de cors

https://www.npmjs.com/package/cors

Karthik
la source
3
app.all('*', function(req, res,next) {
    /**
     * Response settings
     * @type {Object}
     */
    var responseSettings = {
        "AccessControlAllowOrigin": req.headers.origin,
        "AccessControlAllowHeaders": "Content-Type,X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5,  Date, X-Api-Version, X-File-Name",
        "AccessControlAllowMethods": "POST, GET, PUT, DELETE, OPTIONS",
        "AccessControlAllowCredentials": true
    };

    /**
     * Headers
     */
    res.header("Access-Control-Allow-Credentials", responseSettings.AccessControlAllowCredentials);
    res.header("Access-Control-Allow-Origin",  responseSettings.AccessControlAllowOrigin);
    res.header("Access-Control-Allow-Headers", (req.headers['access-control-request-headers']) ? req.headers['access-control-request-headers'] : "x-requested-with");
    res.header("Access-Control-Allow-Methods", (req.headers['access-control-request-method']) ? req.headers['access-control-request-method'] : responseSettings.AccessControlAllowMethods);

    if ('OPTIONS' == req.method) {
        res.send(200);
    }
    else {
        next();
    }


});
Wiki
la source
2

Ajoutez le code suivant dans app.js de NODEJ Restful api pour éviter l'erreur "Access-Control-Allow-Origin" dans angular 6 ou tout autre framework

var express = require('express');
var app = express();

var cors = require('cors');
var bodyParser = require('body-parser');

//enables cors
app.use(cors({
  'allowedHeaders': ['sessionId', 'Content-Type'],
  'exposedHeaders': ['sessionId'],
  'origin': '*',
  'methods': 'GET,HEAD,PUT,PATCH,POST,DELETE',
  'preflightContinue': false
}));
Ezhil Arasan
la source
1

Vous pouvez utiliser "$ http.jsonp"

OU

Ci-dessous, le travail autour de Chrome pour les tests locaux

Vous devez ouvrir votre chrome avec la commande suivante. (Appuyez sur la fenêtre + R)

Chrome.exe --allow-file-access-from-files

Remarque: votre chrome ne doit pas être ouvert. Lorsque vous exécutez cette commande, chrome s'ouvre automatiquement.

Si vous entrez cette commande dans l'invite de commande, sélectionnez votre répertoire d'installation de Chrome, puis utilisez cette commande.

Ci-dessous le code de script pour chrome ouvert dans MAC avec "--allow-file-access-from-files"

set chromePath to POSIX path of "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" 
set switch to " --allow-file-access-from-files"
do shell script (quoted form of chromePath) & switch & " > /dev/null 2>&1 &"

deuxième option

Vous pouvez simplement utiliser open (1) pour ajouter les drapeaux: open -a 'Google Chrome' --args --allow-file-access-from-files

JQuery Guru
la source
Et sur MAC ?? Chrome.exe --allow-file-access-from-files
user1336103
/ Applications / Google \ Chrome.app/Contents/MacOS/Google \ Chrome --allow-file-access-from-files parvient à ouvrir Chrome mais le message affiche toujours "XMLHttpRequest ne peut pas charger localhost: 3000. Origine localhost: 8888 est non autorisé par Access-Control-Allow-Origin. "
user1336103
+1 Je peux confirmer que cela fonctionne avec l'option Mac en utilisant 'open'. Mon cas est un peu différent car je teste simplement un site entièrement téléchargé qui accède à certains fichiers JSON locaux.
spong
0

/**
 * Allow cross origin to access our /public directory from any site.
 * Make sure this header option is defined before defining of static path to /public directory
 */
expressApp.use('/public',function(req, res, next) {
    res.setHeader("Access-Control-Allow-Origin", "*");
    // Request headers you wish to allow
    res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    // Set to true if you need the website to include cookies in the requests sent
    res.setHeader('Access-Control-Allow-Credentials', true);
    // Pass to next layer of middleware
    next();
});


/**
 * Server is about set up. Now track for css/js/images request from the 
 * browser directly. Send static resources from "./public" directory. 
 */
expressApp.use('/public', express.static(path.join(__dirname, 'public')));
If you want to set Access-Control-Allow-Origin to a specific static directory you can set the following.

Luton Datta
la source