Izinkan permintaan CORS REST ke aplikasi Express / Node.js di Heroku

97

Saya telah menulis REST API pada kerangka kerja ekspres untuk node.js yang berfungsi untuk permintaan dari konsol js di Chrome, dan bilah URL, dll. Sekarang saya mencoba membuatnya berfungsi untuk permintaan dari aplikasi lain, pada yang berbeda domain (CORS).

Permintaan pertama, yang dibuat secara otomatis oleh javascript front end, adalah ke / api / search? Uri =, dan tampaknya gagal pada permintaan OPTIONS "preflight".

Di aplikasi ekspres saya, saya menambahkan header CORS, menggunakan:

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

dan:

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

Dari konsol Chrome saya mendapatkan header ini:

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

Metode Permintaan: OPSI

Kode Status: 200 OK

Minta Header

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

Parameter String Kueri

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

Header Respons

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

Apakah ini terlihat seperti kurangnya header yang tepat yang dikirim oleh aplikasi API?

Terima kasih.

Jamie Folsom
sumber
Saya mendapatkan kesalahan ini dalam kode yang tidak saya tulis, tetapi saya tidak memahami kebutuhan penangan untuk OPTIONSmetode ini. Bisakah seseorang membantu saya untuk memahami mengapa tidak menangani hanya POSTmetode alih-alih menangani keduanyaPOST dan OPTIONS metode?
Ulysses Alves
Mungkin juga ingin menyertakan PATCHjika Anda akan menggunakannya alih-alih PUTmemperbarui sumber daya
Danny

Jawaban:

66

Saya telah memeriksa kode Anda di aplikasi ExpressJS yang bersih dan berfungsi dengan baik.

Coba pindahkan Anda app.use(allowCrossDomain)ke atas fungsi konfigurasi.

Olegas
sumber
8
Alasannya adalah karena Anda harus menentukannya sebelum app.use(app.router);Cheers!
Michal
Dalam kasus saya, POST berikutnya tidak dipanggil setelah mengirim kembali res.send (200) ketika req.method == 'OPTIONS'. apakah saya melewatkan hal lain?
Aldo
2Aldo: Kode diperlukan. Mungkin Anda lupa beberapa header? Jika klien Anda tidak mengirim POST setelah server Anda menerima permintaan OPTIONS pra-penerbangan dengan benar, coba periksa konsol alat pengembang. WebKit mencatat jenis error ini ke konsol web inspector.
Olegas
1
@ConnorLech Sangat bagus. Saya telah melakukan pendekatan allowCrossDomain seperti di atas dan lelah berurusan dengan semua manajemen header itu. Juga - karena kami hanya membutuhkan CORS untuk dev, tidak masuk akal untuk mencurahkan begitu banyak siklus untuk mencari tahu apa yang sedang terjadi. Senang ada dukungan node.js untuk memungkinkan ini dengan mudah.
Steven
1
@ConnorLeech Saya pikir Anda harus menambahkan komentar Anda sebagai jawaban ... berfungsi seperti suguhan, dan itu bagus dan sederhana
drmrbrewer
4

untuk mendukung cookie dengan Kredensial, Anda memerlukan baris ini xhr.withCredentials = true;

mdn docs xhr.withCredentials

Di Server Ekspres, tambahkan blok ini sebelum yang lainnya

`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();
});`
doron aviguy
sumber
4

Saya menambahkan ini sebagai jawaban hanya karena kiriman asli dimasukkan sebagai komentar dan karena itu benar-benar diabaikan oleh Anda saat pertama kali saya membuka halaman ini.

Seperti yang ditunjukkan @ConnorLeech dalam komentarnya untuk jawaban yang diterima di atas, ada paket npm yang sangat berguna yang disebut, tidak mengherankan, cors . Penggunaannya sesederhana var cors = require('cors'); app.use(cors());(sekali lagi, diambil dari jawaban Mr. Leech) dan juga dapat diterapkan dengan cara yang lebih ketat dan dapat dikonfigurasi seperti yang diuraikan dalam dokumen mereka .

Mungkin juga penting untuk menunjukkan bahwa komentar asli yang saya rujuk di atas dibuat pada tahun 2014. Sekarang tahun 2019 dan melihat halaman github paket npm , repo telah diperbarui paling lambat sembilan hari yang lalu.

flyingace
sumber
0

Itu tidak mungkin menjadi kasus bagi kebanyakan orang yang menelusuri pertanyaan ini tetapi saya memiliki masalah yang sama persis dan solusinya tidak terkait CORS .

Ternyata rahasia Token Web JSON stringtidak ditentukan dalam variabel lingkungan, jadi token tidak dapat ditandatangani. Hal ini disebabkan oleh POSTpermintaan apa pun yang mengandalkan pemeriksaan atau penandatanganan token untuk mendapatkan waktu tunggu dan mengembalikan 503kesalahan, memberi tahu browser bahwa ada yang salah dalamCORS , padahal sebenarnya tidak. Menambahkan variabel lingkungan di Heroku menyelesaikan masalah.

Saya harap ini membantu seseorang.

CatBrownie
sumber
Ya, itulah masalah saya. Bisakah Anda lebih spesifik bagaimana Anda memecahkan masalah. Saya masih dalam pengembangan dan menjalankan paket Express.js w / node cors.
Alan
@alan Saya menggunakan janji untuk memverifikasi token dalam aplikasi saya, beberapa bagaimana jika rahasia JWT tidak ditentukan, janji tidak akan pernah terselesaikan, inilah kode yang saya gunakan jika Anda memerlukan referensi lebih lanjut.
CatBrownie
Terima kasih telah menanggapi. Saya akan memeriksa kode. Secara rahasia, saya berasumsi Anda berbicara tentang kunci pribadi kedua. Saya menggunakan oauth2.
Alan
Saya akan menambahkan bahwa janji yang gagal akan menghasilkan kesalahan yang menyesatkan ini! Saya harus eksplisit tentang versi Node yang digunakan atau panggilan database saya (mongo) hanya menggantung dan satu-satunya hal yang dapat dikatakan browser kepada saya adalah 503 dan kemudian beberapa kekonyolan terkait Cors. Kesalahan ini benar-benar membuat saya bingung selama ini app.use(cors());.
alfanumerik0101
0

masukkan deskripsi gambar di sini

Ikuti langkah-langkah di bawah ini:

npm install cors --save

Di dalam file root js Anda:

 var express = require('express') 
 var cors = require('cors')
 var app = express()
 app.use(cors())
Paridhi shah
sumber