วิธีเปิดใช้งานการแชร์ทรัพยากรข้ามแหล่งที่มา (CORS) ในเฟรมเวิร์ก express.js บน node.js


101

ฉันกำลังพยายามสร้างเว็บเซิร์ฟเวอร์ใน node.js ที่รองรับการเขียนสคริปต์ข้ามโดเมนในขณะที่ยังให้ไฟล์แบบคงที่จากไดเร็กทอรีสาธารณะ ฉันใช้ express.js และไม่แน่ใจว่าจะอนุญาตให้ใช้สคริปต์ข้ามโดเมนได้อย่างไร ( Access-Control-Allow-Origin: *)

ฉันเห็นโพสต์นี้ซึ่งฉันไม่พบว่ามีประโยชน์

var express = require('express')
  , app = express.createServer();

app.get('/', function (req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    next();
});

app.configure(function () {
    app.use(express.methodOverride());
    app.use(express.bodyParser());
    app.use(app.router);
});

app.configure('development', function () {

    app.use(express.static(__dirname + '/public'));
    app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

app.configure('production', function () {


    var oneYear = 31557600000;
    //    app.use(express.static(__dirname + '/public', { maxAge: oneYear }));
    app.use(express.static(__dirname + '/public'));
    app.use(express.errorHandler());
});

app.listen(8888);
console.log('express running at http://localhost:%d', 8888);

สังเกต app.all vs app.get เป็น OPTIONS ขอไม่ GET
Shimon Doodkin

ดูlocal-web-serverสำหรับตัวอย่างของโหนดธรรมดาเว็บเซิร์ฟเวอร์แบบคงที่ซึ่งรองรับ CORS
Lloyd

ดู enable-cors.org/server_apache.html สำหรับข้อมูลเพิ่มเติม
Mostafa

"Access-Control-Allow-Origin", "*"ทำให้ API ของคุณน่าสนใจสำหรับแอปฟิชชิง พิจารณาอนุญาตเฉพาะต้นกำเนิดที่รู้จัก
Martin Schneider

คำตอบ:


159

ดูตัวอย่างจาก enable-cors.org :

ในแอป ExpressJS ของคุณบน node.js ให้ทำสิ่งต่อไปนี้กับเส้นทางของคุณ:

app.all('/', function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "X-Requested-With");
  next();
 });

app.get('/', function(req, res, next) {
  // Handle the get for this route
});

app.post('/', function(req, res, next) {
 // Handle the post for this route
});

สายแรก (app.allควร ) ก่อนเส้นทางอื่น ๆ ทั้งหมดในแอปของคุณ (หรืออย่างน้อยที่สุดที่คุณต้องการให้เปิดใช้งาน CORS)

[แก้ไข]

หากคุณต้องการให้ส่วนหัวแสดงสำหรับไฟล์แบบคงที่ด้วยให้ลองทำเช่นนี้ (ตรวจสอบให้แน่ใจว่าอยู่ก่อนการเรียกไปที่use(express.static()):

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "X-Requested-With");
  next();
});

ฉันทดสอบสิ่งนี้ด้วยรหัสของคุณและได้รับส่วนหัวของเนื้อหาจากpublicไดเรกทอรี:

var express = require('express')
  , app = express.createServer();

app.configure(function () {
    app.use(express.methodOverride());
    app.use(express.bodyParser());
    app.use(function(req, res, next) {
      res.header("Access-Control-Allow-Origin", "*");
      res.header("Access-Control-Allow-Headers", "X-Requested-With");
      next();
    });
    app.use(app.router);
});

app.configure('development', function () {
    app.use(express.static(__dirname + '/public'));
    app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

app.configure('production', function () {
    app.use(express.static(__dirname + '/public'));
    app.use(express.errorHandler());
});

app.listen(8888);
console.log('express running at http://localhost:%d', 8888);

แน่นอนคุณสามารถรวมฟังก์ชันไว้ในโมดูลเพื่อให้คุณสามารถทำสิ่งต่างๆเช่น

// cors.js

module.exports = function() {
  return function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    next();
  };
}

// server.js

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

สวัสดีขอบคุณสำหรับการตอบกลับของคุณ ฉันทำตามที่คุณแนะนำ (ส่วนแรก แต่ยังไม่เห็นความแตกต่างในส่วนหัวของคำขอ) ฉันได้แนบรหัสปัจจุบันของฉันไว้ด้านบน คุณอธิบายได้ไหมว่าฉันจะรวมโซลูชันที่เหลือเข้ากับสิ่งนั้นได้อย่างไร
Guy

1
ผมแปลกใจว่าตั้งแต่คุณuseไอเอ็นจีapp.routerก่อนexpress.staticว่ามันไม่ได้ปรับเปลี่ยนส่วนหัวสำหรับไฟล์คงที่; ไม่ว่าในกรณีใดฉันได้อัปเดตคำตอบเพื่อให้ใช้งานได้
Michelle Tilley

ขอบคุณ! ฉันเห็นว่าคุณพูดถูก เนื้อหาที่ได้รับจากเซิร์ฟเวอร์มาพร้อมกับส่วนหัวที่ร้องขอ ฉันอาจไม่ชัดเจนเกี่ยวกับปัญหาที่แท้จริงของฉัน ฉันกำลังพยายามเรียก API ไปยังเซิร์ฟเวอร์ภายนอกด้วยคำสั่ง get และนั่นคือสิ่งที่ฉันได้รับข้อผิดพลาด: XMLHttpRequest ไม่สามารถโหลดSOMEURL.comได้ Origin localhost: 8888ไม่ได้รับอนุญาตจาก Access-Control-Allow-Origin
Guy

ฉันอาจจะเข้าใจผิด คุณเป็นผู้ควบคุมเซิร์ฟเวอร์ที่ SOMEURL.com หรือไม่?
Michelle Tilley

ขอโทษตอนนี้ฉันเข้าใจคำตอบของคุณแล้ว ขอบคุณมาก. ขอขอบคุณสำหรับความช่วยเหลือ :)
Guy

58

ตามวิธีแก้ปัญหาของ @Michelle Tilley เห็นได้ชัดว่ามันไม่ได้ผลสำหรับฉันในตอนแรก ไม่แน่ใจว่าเพราะเหตุใดฉันอาจใช้ Chrome และโหนดเวอร์ชันอื่น หลังจากปรับแต่งเล็กน้อยแล้วตอนนี้ก็ใช้งานได้สำหรับฉัน

app.all('*', function(req, res, next) {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  next();
});

ในกรณีที่มีคนประสบปัญหาคล้ายกับของฉันสิ่งนี้อาจเป็นประโยชน์


สังเกต app.all vs app.get เป็น OPTIONS ขอไม่ GET
Shimon Doodkin

สิ่งนี้ใช้ได้กับฉัน (ฉันกำลังดึงวัตถุโดยใช้ Backbone) ฉันกำลังพยายามคิดว่ามันจะทำงานใน IE 8 ได้ไหม ... ดูเหมือนว่ามันควรจะเป็น แต่ฉันไม่รู้ว่าจำเป็นต้องมีอะไรพิเศษสำหรับ "XDomainRequest" นี้หรือไม่ ... developer.mozilla.org/en- US / docs / HTTP / …
Adam Loving

ข้อมูลบางส่วนสำหรับผู้ใช้ในอนาคต: ฉันกำลังเปลี่ยนชื่อโดเมนของฉันไปยังที่เก็บ heroku ซึ่งเป็นสาเหตุที่ฉันพบปัญหานี้ อย่างไรก็ตามคำตอบแรกใช้ได้ผลในพื้นที่ แต่ไม่ใช่หลังจากที่ฉันส่งไปที่ heroku อย่างไรก็ตามคำตอบนี้ใช้ได้ผลหลังจากผลักดันไปที่ heroku
Kris Hollenbeck

@KrisHollenbeck นี่ไม่ได้ผลสำหรับฉันใน heroku คุณทำอย่างอื่นหรือไม่?
Ben Craig

@ BenCraig ไม่ แต่จริงๆแล้วมันหยุดทำงานสำหรับฉันหลังจากลองครั้งแรก ดังนั้นฉันก็ยังคงมีปัญหานี้เช่นกัน
Kris Hollenbeck

11

ลองใช้โมดูลcors npm นี้

var cors = require('cors')

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

โมดูลนี้มีคุณสมบัติมากมายในการปรับแต่งการตั้งค่า cors อย่างละเอียดเช่นรายการโดเมนที่อนุญาตพิเศษการเปิดใช้งาน cors สำหรับ apis เฉพาะเป็นต้น


2

ฉันใช้สิ่งนี้:

var app = express();

app
.use(function(req, res, next){
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Headers', 'X-Requested-With');
    next();
})
.options('*', function(req, res, next){
    res.end();
})
;

h.readFiles('controllers').forEach(function(file){
  require('./controllers/' + file)(app);
})
;

app.listen(port);
console.log('server listening on port ' + port);

รหัสนี้ถือว่าคอนโทรลเลอร์ของคุณอยู่ในไดเร็กทอรีคอนโทรลเลอร์ แต่ละไฟล์ในไดเร็กทอรีนี้ควรเป็นดังนี้:

module.exports = function(app){

    app.get('/', function(req, res, next){
        res.end('hi');
    });

}


0

คุณต้องตั้งค่าAccess-Control-Allow-Credentials: trueหากคุณต้องการใช้ "คุกกี้" ผ่าน "ข้อมูลรับรอง"

app.all('*', function(req, res, next) {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Credentials', true);
  res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  next();
});

0
app.use(function(req, res, next) {
var allowedOrigins = [
  "http://localhost:4200"
];
var origin = req.headers.origin;
console.log(origin)
console.log(allowedOrigins.indexOf(origin) > -1)
// Website you wish to allow to
if (allowedOrigins.indexOf(origin) > -1) {
  res.setHeader("Access-Control-Allow-Origin", origin);
}

// res.setHeader("Access-Control-Allow-Origin", "http://localhost:4200");

// 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,Authorization"
);

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

});

เพิ่มรหัสนี้ในไฟล์ index.js หรือ server.js ของคุณและเปลี่ยนอาร์เรย์ต้นทางที่อนุญาตตามความต้องการของคุณ


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.