Cho phép yêu cầu CORS REST đối với ứng dụng Express / Node.js trên Heroku


97

Tôi đã viết một API REST trên khung express cho node.js hoạt động cho các yêu cầu từ bảng điều khiển js trong Chrome và thanh URL, v.v. Tôi hiện đang cố gắng làm cho nó hoạt động với các yêu cầu từ một ứng dụng khác, trên một ứng dụng khác miền (CORS).

Yêu cầu đầu tiên, được tạo tự động bởi giao diện người dùng javascript, là / api / search? Uri =, và có vẻ như không thành công với yêu cầu OPTIONS "preflight".

Trong ứng dụng express của tôi, tôi đang thêm các tiêu đề CORS, sử dụng:

var allowCrossDomain = function(req, res, next) {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
    res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');

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

và:

app.configure(function () {
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);
  app.use(allowCrossDomain);
  app.use(express.static(path.join(application_root, "public")));
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

Từ bảng điều khiển Chrome, tôi nhận được các tiêu đề sau:

URL yêu cầu: http: //furious-night-5419.herokuapp.com/api/search? Uri = http% 3A% 2F% 2Flocalhost% 3A5000% 2Fcollections% 2F1% 2Fdocuments% 2F1

Phương thức yêu cầu: OPTIONS

Mã trạng thái: 200 OK

Yêu cầu tiêu đề

Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:origin, x-annotator-auth-token, accept
Access-Control-Request-Method:GET
Connection:keep-alive
Host:furious-night-5419.herokuapp.com
Origin:http://localhost:5000
Referer:http://localhost:5000/collections/1/documents/1
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.56 Safari/536.5

Tham số chuỗi truy vấn

uri:http://localhost:5000/collections/1/documents/1

Tiêu đề phản hồi

Allow:GET
Connection:keep-alive
Content-Length:3
Content-Type:text/html; charset=utf-8
X-Powered-By:Express

Điều này trông giống như thiếu tiêu đề thích hợp được gửi bởi ứng dụng API?

Cảm ơn.


Tôi gặp lỗi này trong một mã mà tôi không viết, nhưng tôi không hiểu sự cần thiết của trình xử lý cho OPTIONSphương thức. Ai đó có thể vui lòng giúp tôi hiểu tại sao không xử lý chỉ là POSTphương pháp thay vì xử lý cả hai POST OPTIONS phương pháp?
Ulysses Alves

Cũng có thể muốn bao gồm PATCHnếu bạn sẽ sử dụng nó thay vì PUTphải cập nhật một nguồn tài nguyên
Danny

Câu trả lời:


65

Tôi đã đánh dấu mã của bạn trên một ứng dụng ExpressJS sạch sẽ và nó hoạt động tốt.

Hãy thử di chuyển của bạn app.use(allowCrossDomain)lên đầu chức năng cấu hình.


8
Lý do nó làm được là vì bạn cần phải xác định nó trước khi app.use(app.router);Cheers!
Michal

Trong trường hợp của tôi, POST tiếp theo không được gọi sau khi gửi lại res.send (200) khi req.method == 'OPTIONS'. tôi còn thiếu gì nữa không?
Aldo

2Aldo: Cần mã. Có thể bạn quên một số tiêu đề? Nếu khách hàng của bạn không gửi ĐĂNG sau khi máy chủ của bạn được phân phát chính xác yêu cầu TÙY CHỌN trước khi bắt đầu, hãy thử kiểm tra bảng điều khiển công cụ dành cho nhà phát triển. WebKit ghi lại loại lỗi này vào bảng điều khiển của trình kiểm tra web.
Olegas

1
@ConnorLosystem Rất hay. Tôi đã thực hiện phương pháp allowCrossDomain như trên và cảm thấy mệt mỏi khi phải xử lý tất cả các mgmt tiêu đề đó. Ngoài ra - vì chúng tôi chỉ cần CORS cho nhà phát triển, nên không có ý nghĩa gì khi dành quá nhiều chu kỳ để tìm ra những gì đang xảy ra. Rất vui khi có sự hỗ trợ của node.js để dễ dàng cho phép điều này.
Steven

1
@ConnorLeech Tôi nghĩ bạn nên thêm nhận xét của bạn như một câu trả lời ... hoạt động giống như một bữa tiệc, và nó đẹp và đơn giản
drmrbrewer

4

để hỗ trợ cookie với Thông tin đăng nhập, bạn cần dòng này xhr.withCredentials = true;

mdn docs xhr.withCredentials

Trong Express Server, hãy thêm khối này vào trước tất cả khối khác

`app.all('*', function(req, res, next) {
     var origin = req.get('origin'); 
     res.header('Access-Control-Allow-Origin', origin);
     res.header("Access-Control-Allow-Headers", "X-Requested-With");
     res.header('Access-Control-Allow-Headers', 'Content-Type');
     next();
});`

4

Tôi chỉ thêm điều này như một câu trả lời vì bài đăng ban đầu được đưa vào dưới dạng nhận xét và do đó, nó đã bị bạn thực sự bỏ qua ngay lần đầu tiên tôi xem qua trang này.

Như @ConnorLeech chỉ ra trong bình luận của mình để câu trả lời được chấp nhận ở trên, có một gói NPM rất tiện gọi, không có gì ngạc nhiên CORS . Việc sử dụng nó đơn giản như var cors = require('cors'); app.use(cors());(một lần nữa, được trích dẫn từ câu trả lời của ông Leech) và cũng có thể được áp dụng theo cách chặt chẽ hơn, có thể định cấu hình cao hơn như được nêu trong tài liệu của họ .

Cũng có thể đáng để chỉ ra rằng nhận xét ban đầu mà tôi đề cập ở trên được đưa ra vào năm 2014. Bây giờ là năm 2019 và nhìn vào trang github của gói npm, repo đã được cập nhật gần đây nhất là chín ngày trước.


0

Nó không thể là trường hợp cho hầu hết mọi người duyệt câu hỏi này nhưng tôi đã gặp vấn đề chính xác này và giải pháp không liên quan đến CORS.

Hóa ra rằng bí mật stringmã thông báo web JSON không được xác định trong các biến môi trường, vì vậy mã thông báo không thể được ký. Điều này gây ra bất kỳ POSTyêu cầu nào dựa vào việc kiểm tra hoặc ký mã thông báo để hết thời gian chờ và trả về 503lỗi, cho trình duyệt biết rằng có điều gì đó không ổn trong CORSđó không đúng. Thêm biến môi trường trong Heroku đã giải quyết được vấn đề.

Tôi hi vọng điêu nay se giup được ai đo.


Vâng, đó là vấn đề với tôi. Bạn có thể nói rõ hơn cách bạn giải quyết vấn đề. Tôi vẫn đang trong quá trình phát triển và đang chạy trên gói Express.js w / node cors.
Alan

@alan Tôi đang sử dụng lời hứa để xác minh mã thông báo trong ứng dụng của mình, một số cách nếu bí mật JWT không được xác định, lời hứa sẽ không bao giờ giải quyết, đây là tôi đang sử dụng nếu bạn cần tham khảo thêm.
CatBrownie

Cảm ơn vì đã phản hồi. Tôi sẽ xem qua mã. Bằng bí mật, tôi cho rằng bạn đang nói về khóa riêng thứ hai. Tôi đang sử dụng oauth2.
Alan

Tôi sẽ nói thêm rằng bất kỳ lời hứa nào không thành công sẽ tạo ra lỗi gây hiểu nhầm này! Tôi phải nói rõ về một phiên bản Node đang được sử dụng nếu không các lệnh gọi cơ sở dữ liệu của tôi (mongo) chỉ bị treo và điều duy nhất mà trình duyệt có thể cho tôi biết là 503 và sau đó là một số lỗi liên quan đến Cors. Lỗi này thực sự khiến tôi bối rối trong thời gian dài nhất app.use(cors());.
alphanumeric0101
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.