Kein 'Access-Control-Allow-Origin' - Knoten- / Apache-Port-Problem

260

Ich habe eine kleine API mit Node / Express erstellt und versucht, Daten mit Angularjs abzurufen, aber da meine HTML-Seite unter Apache auf localhost: 8888 ausgeführt wird und die Node-API auf Port 3000 abgehört wird, erhalte ich die No 'Access-Control- Allow-Origin '. Ich habe versucht, node-http-proxyVhosts Apache zu verwenden, habe aber nicht viel Erfolg. Siehe vollständigen Fehler und Code unten.

XMLHttpRequest kann localhost: 3000 nicht laden. In der angeforderten Ressource ist kein Header 'Access-Control-Allow-Origin' vorhanden. Origin 'localhost: 8888' ist daher kein Zugriff gestattet. "

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

Winkelcode

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
quelle

Antworten:

621

Fügen Sie Ihrer NodeJS / Express-App die folgende Middleware hinzu (ich habe einige Kommentare hinzugefügt):

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

Ich hoffe, das hilft!

jvandemo
quelle
2
Können Sie genau angeben, wohin das führt? Ich habe den folgenden Code auf meinem Server. Geht es danach gleich? var app = require ('express') (), server = require ('http'). createServer (app), io = require ('socket.io'). listen (server), request = require ("request") , url = require ("url"); server.listen (6969); // geht es hier hin auf einer neuen Linie?
Art Geigel
1
@jvandemo muss ich die app.get ('/', Funktion (req, res) in ... Funktion (req, res, next) ändern?
Sangram Singh
10
Du bist momentan meine Lieblingsperson. Danke dir. Können wir einen Hinweis hinzufügen, dass dieser Code vorkommen muss, bevor die Routen für Noobs wie mich definiert werden?
gegillam
1
Wie funktioniert dies bei Verwendung des Anforderungsmoduls?
Rohit Tigga
2
In meinem Fall hat es nicht funktioniert. Der folgende Fehler wird weiterhin angezeigt: "Die Antwort auf die Preflight-Anforderung besteht die Zugriffssteuerungsprüfung nicht: In der angeforderten Ressource ist kein Header" Zugriffssteuerung-Zulassen-Ursprung "vorhanden. Der Ursprung" abc.xyz.net:212 "ist daher nicht zulässig Zugriff. Die Antwort hatte den HTTP-Statuscode 500. "
user1451111
96

Die akzeptierte Antwort ist in Ordnung. Wenn Sie etwas Kürzeres bevorzugen, können Sie ein Plugin namens cors verwenden, das für Express.js verfügbar ist

Für diesen speziellen Fall ist es einfach zu bedienen:

var cors = require('cors');

// use it before all route definitions
app.use(cors({origin: 'http://localhost:8888'}));
Fabiano Soriani
quelle
3
Ich musste es verwenden, {origin: 'null'}damit es funktioniert ... Anscheinend sendet mein Browser nullals Ursprung?
Ricardo Cruz
2
Warum das Rad neu erfinden? Ich bin immer für eine Paketlösung im Vergleich zu Code-Snippet
Pierre
süße kleine Bibliothek, die meinen Anwendungsfall, verschiedene Methoden unterschiedlicher Herkunft zu wollen, ganz gut handhabte ... und weniger Code-Müdigkeit für den nächsten, der sie sich ansieht.
Kyle Baker
6
Danke, app.use(cors({origin: '*'}));hat für mich gearbeitet, laut enable-cors .
Danialk
2
Ich schlage vor, einen Blick auf die npm cors-Seite zu um sie besser nutzen zu können. Es hat mir die Dinge sehr klar gemacht =).
13013SwagR
30

Eine andere Möglichkeit besteht darin, einfach die Überschriften zu Ihrer Route hinzuzufügen:

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
quelle
8
)von Smiley verwirrte mich
diEcho
17

Die beste Antwort hat für mich gut funktioniert, außer dass ich mehr als eine Domain auf die Whitelist setzen musste.

Auch Top-Antwort leidet unter der Tatsache, dass OPTIONS Anfrage nicht von der Middleware bearbeitet wird und Sie sie nicht automatisch erhalten.

Ich speichere Domains auf der Whitelist wie allowed_originsin der Express-Konfiguration und stelle originseitdem die richtige Domain entsprechend dem Header einAccess-Control-Allow-Origin nicht mehr als eine Domain angegeben werden kann.

Folgendes habe ich erreicht:

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
quelle
Ist dies das gleiche 'if (app.get (' erlaubte Ursprünge '). IndexOf (Ursprung)! == - 1)?'?
Rune Jeppesen
13

Der Antwortcode erlaubt nur localhost: 8888. Dieser Code kann nicht für die Produktion oder für andere Server- und Portnamen bereitgestellt werden.

Verwenden Sie stattdessen Folgendes, damit es für alle Quellen funktioniert:

// 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
quelle
2
Das funktioniert bei mir nicht! "* ist kein gültiger Ursprung". Es scheint, dass das Zeichen * nicht als Platzhalter erkannt wird.
Francesco
Für mich geht das. dh mit Platzhalter '*'. funktioniert sowohl für Chrom als auch für Safari.
AnBisw
Danke;) Funktioniert gut
Mauro
9

Installieren Sie die cors-Abhängigkeit in Ihrem Projekt:

npm i --save cors

Fügen Sie Ihrer Serverkonfigurationsdatei Folgendes hinzu:

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

Es funktioniert bei mir mit 2.8.4 cors Version.

monikaja
quelle
"cors": "^2.8.5", "express": "^4.16.3",funktioniert gut nur mit der vorgeschlagenen Zeile @monikaja. Vielen Dank!
RamiroIsBack
Auf diese Weise können alle Ursprünge / Domänen auf die App zugreifen, was Sie normalerweise nicht möchten. Geben Sie stattdessen nur die zulässigen Domänen an.
Lacho Tomov
7

Das hat bei mir funktioniert.

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

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

Sie können * an Ihre Bedürfnisse anpassen. Hoffe das kann helfen.

dmx
quelle
7

Hallo, das passiert, wenn das Frontend und das Backend auf verschiedenen Ports laufen. Der Browser blockiert die Antworten aus dem Backend, da keine CORS-Header vorhanden sind. Die Lösung besteht darin, die CORS-Header zur Backend-Anforderung hinzuzufügen. Am einfachsten ist es, das cors npm-Paket zu verwenden.

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

Dadurch werden CORS-Header in allen Ihren Anforderungen aktiviert. Weitere Informationen finden Sie in der Dokumentation zu cors

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

Karthik
quelle
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
quelle
2

Fügen Sie den folgenden Code in app.js von NODEJ Restful API hinzu, um den Fehler "Access-Control-Allow-Origin" in Winkel 6 oder einem anderen Framework zu vermeiden

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
quelle
1

Sie können "$ http.jsonp" verwenden

ODER

Nachfolgend finden Sie die Problemumgehung für Chrom für lokale Tests

Sie müssen Ihr Chrom mit dem folgenden Befehl öffnen. (Drücken Sie Fenster + R)

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

Hinweis: Ihr Chrom darf nicht geöffnet sein. Wenn Sie diesen Befehl ausführen, wird Chrome automatisch geöffnet.

Wenn Sie diesen Befehl an der Eingabeaufforderung eingeben, wählen Sie Ihr Chrome-Installationsverzeichnis aus und verwenden Sie diesen Befehl.

Unten Skriptcode für Open Chrome in MAC mit "--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 &"

zweite Optionen

Sie können einfach open (1) verwenden , um die Flags hinzuzufügen: open -a 'Google Chrome' --args --allow-file-access-from-files

JQuery Guru
quelle
Wie wäre es mit MAC? Chrome.exe - Erlaube-Datei-Zugriff-aus-Dateien
user1336103
/ Applications / Google \ Chrome.app/Contents/MacOS/Google \ Chrome - Der Zugriff von Dateien auf Dateien kann nur geöffnet werden. In der Meldung wird jedoch weiterhin "XMLHttpRequest kann localhost: 3000 nicht laden . Origin localhost: 8888 is nicht erlaubt durch Access-Control-Allow-Origin. "
user1336103
+1 Ich kann bestätigen, dass dies mit der Mac-Option funktioniert, indem ich 'Öffnen' verwende. Mein Fall ist etwas anders, da ich einfach eine vollständig heruntergeladene Site teste, die auf einige lokale JSON-Dateien zugreift.
Schwamm
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
quelle