web-dev-qa-db-fra.com

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

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 s'exécute sous Apache sur localhost: 8888 et que l'API de nœud est à l'écoute sur le port 3000, j'obtiens le No 'Access-Control- Allow-Origin '. J'ai essayé d'utiliser node-http-proxy et Vhosts Apache mais je n'ai pas eu beaucoup de succès, veuillez consulter 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. Origin 'accès localhost: 8888' n'est donc pas autorisé."

// 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')


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

   $http.get('localhost:3000').success(function(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>
222
user1336103

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 ça t'as aidé!

558
jvandemo

La réponse acceptée convient, 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, dans ce cas particulier:

var cors = require('cors');

// use it before all route definitions
app.use(cors({Origin: 'http://localhost:8888'}));
86
Fabiano Soriani

Une autre solution 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:)');
});
28
Asaf Hananel

Le réponse du haut a bien fonctionné pour moi, sauf que je devais ajouter à la liste blanche plus d'un domaine.

En outre, top answer souffre du fait que la requête OPTIONS n'est pas gérée par le middleware et que vous ne l'obtenez pas automatiquement.

Je stocke les domaines figurant sur la liste blanche sous le nom allowed_origins dans la configuration Express et mets le domaine approprié en fonction de l'en-tête Origin, car Access-Control-Allow-Origin n'autorise pas la spécification de plusieurs domaines.

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);
});
14
Dan Abramov

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

Pour que cela fonctionne pour toutes les sources, utilisez ceci à la place:

// 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();
});
12
Vicheanak

Installez la dépendance cors dans votre projet:

npm i --save cors

Ajoutez à votre fichier de configuration du serveur ce qui suit:

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

Cela fonctionne pour moi avec la version 2.8.4 cors.

6
monikaja

Cela a fonctionné pour moi.

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

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

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

4
dmx
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();
    }


});
3
Wiki
//Add following code in app.js of NODEJ Restful api to avoid "Access-Control-Allow-Origin" error in angular 6 or any other 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
}));
2
Ezhil Arasan

Vous pouvez utiliser "$ http.jsonp"

OR

Vous trouverez ci-dessous la solution de contournement de chrome pour les tests locaux.

Vous devez ouvrir votre chrome avec la commande suivante. (Fenêtre de presse + R)

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

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

Si vous entrez cette commande dans la commande Invite, sélectionnez votre répertoire d'installation chrome, puis utilisez cette commande.

Code de script ci-dessous pour ouvrir chrome 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

1
JQuery Guru

Bonjour, cela se produit lorsque les serveurs frontaux et principaux fonctionnent 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 consiste à ajouter les en-têtes CORS dans la demande principale. Le moyen le plus simple est d'utiliser le paquet cors npm.

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

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

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

0
Karthik S Kumar
/**
 * 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.
0
Luton Datta