Почему добавление заголовков CORS к маршруту OPTIONS не позволяет браузерам получать доступ к моему API? - PullRequest
590 голосов
/ 15 августа 2011

Я пытаюсь поддерживать CORS в моем приложении Node.js, которое использует веб-каркас Express.js.Я прочитал групповое обсуждение Google о том, как с этим справиться, и прочитал несколько статей о том, как работает CORS.Сначала я сделал это (код написан в синтаксисе CoffeeScript):

app.options "*", (req, res) ->
  res.header 'Access-Control-Allow-Origin', '*'
  res.header 'Access-Control-Allow-Credentials', true
  # try: 'POST, GET, PUT, DELETE, OPTIONS'
  res.header 'Access-Control-Allow-Methods', 'GET, OPTIONS'
  # try: 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept'
  res.header 'Access-Control-Allow-Headers', 'Content-Type'
  # ...

Кажется, он не работает.Похоже, мой браузер (Chrome) не отправляет начальный запрос OPTIONS.Когда я только что обновил блок для ресурса, мне нужно отправить перекрестный запрос GET по адресу:

app.get "/somethingelse", (req, res) ->
  # ...
  res.header 'Access-Control-Allow-Origin', '*'
  res.header 'Access-Control-Allow-Credentials', true
  res.header 'Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, OPTIONS'
  res.header 'Access-Control-Allow-Headers', 'Content-Type'
  # ...

Это работает (в Chrome).Это также работает в Safari.

Я читал, что ...

В браузере, реализующем CORS, каждому перекрестному запросу GET или POST предшествует запрос OPTIONS, который проверяетВ порядке ли GET или POST.

Итак, мой главный вопрос: почему этого не происходит в моем случае?Почему не вызывается мой блок app.options?Зачем мне устанавливать заголовки в моем главном блоке app.get?

Ответы [ 28 ]

1 голос
/ 10 февраля 2016

Мне было очень легко сделать это с помощью пакета запросов npm (https://www.npmjs.com/package/request)

Тогда я основал свое решение на этом посте http://blog.javascripting.com/2015/01/17/dont-hassle-with-cors/

'use strict'

const express = require('express');
const request = require('request');

let proxyConfig = {
    url : {
        base: 'http://servertoreach.com?id=',
    }
}

/* setting up and configuring node express server for the application */
let server = express();
server.set('port', 3000);


/* methods forwarded to the servertoreach proxy  */
server.use('/somethingElse', function(req, res)
{
    let url = proxyConfig.url.base + req.query.id;
    req.pipe(request(url)).pipe(res);
});


/* start the server */
server.listen(server.get('port'), function() {
    console.log('express server with a proxy listening on port ' + server.get('port'));
});
0 голосов
/ 20 мая 2019
const express = require("express");
const router = express.Router();
const app = express();
const cors = require("cors"); 



const options = {
  origin: true,
  "Access-Control-Allow-Credentials": true,

  "Access-Control-Allow-Origin": true,
  "Access-Control-Allow-Headers": true,
  "Access-Control-Expose-Headers": true
};


app.use(cors(options));
router.get("/", cors(options), (req, res) => {
  res.render("index", { title: "Express" });
});

module.exports = router;

Для GOOGLE CHROME необходимо добавить расширение «Allow-Control-Allow-Origin»

Заголовок Access-Control-Allow-Origin (заголовок ответа) указывает, можно ли разделить ресурс на основе возврата значения заголовка запроса источника. Заголовок Access-Control-Allow-Origin открывает дверь для перекрестного доступа

Access-Control-Allow-Credentials (заголовок ответа): true используется, чтобы указать, что клиенту разрешено использовать учетные данные. По умолчанию ответы на запросы с учетными данными не могут быть прочитаны клиентским скриптом. Таким образом, вы можете получить доступ к ответу. Кроме того, по умолчанию CORS не включает файлы cookie в запросах с несколькими источниками, и это может привести к классу уязвимостей, который называется подделкой запросов между сайтами или CSRF. Чтобы снизить вероятность появления уязвимостей CSRF в CORS, CORS требует, чтобы и сервер, и клиент подтвердили, что файлы cookie можно включать в запросы.

Access-Control-Expose-Headers (заголовок ответа) указывает, какие заголовки безопасны для показа. Список заголовков ответа можно прочитать. По умолчанию доступны только 6 простых заголовков ответа: Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, Pragma

Access-Control-Request-Headers (заголовок запроса) указывает, какие заголовки HTTP можно использовать во время фактического запроса.

origin = true (заголовок запроса) отражает происхождение запроса. Если значение равно false, Cors будет отключен.

0 голосов
/ 20 апреля 2019

Самый простой подход - установить модуль cors в вашем проекте, используя:

npm i --save cors

Затем в файл вашего сервера импортируйте его, используя следующую команду:

import cors from 'cors';

Затем просто используйте его какпромежуточное программное обеспечение, подобное этому:

app.use(cors());

Надеюсь, это поможет!

0 голосов
/ 02 марта 2019

используя nodejs без экспресс / внешних библиотек. Я использовал приведенный ниже метод в моем файле server.js. Ключевыми частями здесь является получение источника из заголовка запроса, а затем разрешение его в ответе сервера, после чего мы можем установить заголовок, который будет возвращен, включая разрешенный источник, если совпадение найдено.

    **const origin = req.headers.origin;**

      let decoder = new StringDecoder('utf-8');
      let buffer = '';
      req.on('data', function (data) {
        buffer += decoder.write(data);
      });
      req.on('end', function () {
        buffer += decoder.end();

        let chosenHandler = typeof (server.router[trimmedPath]) !== 'undefined' ? server.router[trimmedPath] : handlers.notFound;

const data = { ....data object vars}

// should be wrapped in try catch block
      chosenHandler(data, function (statusCode, payload, contentType) {
        server.processHandlerResponse(res, method, trimmedPath, statusCode, payload, contentType, **origin**);


server.processHandlerResponse = function (res, method, trimmedPath, statusCode, payload, contentType, origin) {
  contentType = typeof (contentType) == 'string' ? contentType : 'json';

  statusCode = typeof (statusCode) == 'number' ? statusCode : 200;

  let payloadString = '';
  if (contentType == 'json') {
    res.setHeader('Content-Type', 'application/json');

    const allowedOrigins = ['https://www.domain1.com', 'https://someotherdomain','https://yetanotherdomain',
    ...// as many as you need
  ];
    **if (allowedOrigins.indexOf(origin) > -1) {
        res.setHeader('Access-Control-Allow-Origin', origin);
    }**
    payload = typeof (payload) == 'object' ? payload : {};
    payloadString = JSON.stringify(payload);
  }

... //  if (other content type) ...rinse and repeat..
0 голосов
/ 02 октября 2018

Ниже код будет работать, но сначала установите Cors по:

установка в минуту - сохранить cors

Тогда:

module.exports = function(app) { 
var express = require("express");
var cors = require('cors');
var router = express.Router();
app.use(cors());

app.post("/movies",cors(), function(req, res) { 
res.send("test");
});
0 голосов
/ 09 июля 2018

В машинописном тексте, если вы хотите использовать пакет node.js cors

/**
* app.ts
* If you use the cors library
*/

import * as express from "express";
[...]
import * as cors from 'cors';

class App {
   public express: express.Application;

   constructor() {
       this.express = express();
       [..]
       this.handleCORSErrors();
   }

   private handleCORSErrors(): any {
       const corsOptions: cors.CorsOptions = {
           origin: 'http://example.com',
           optionsSuccessStatus: 200
       };
       this.express.use(cors(corsOptions));
   }
}

export default new App().express;

Если вы не хотите использовать библиотеки третьей части для обработки ошибок cors, вам нужно изменить метод handleCORSErrors ().

/**
* app.ts
* If you do not use the cors library
*/

import * as express from "express";
[...]

class App {
   public express: express.Application;

   constructor() {
       this.express = express();
       [..]
       this.handleCORSErrors();
   }

   private handleCORSErrors(): any {
       this.express.use((req, res, next) => {
           res.header("Access-Control-Allow-Origin", "*");
           res.header(
               "Access-Control-ALlow-Headers",
               "Origin, X-Requested-With, Content-Type, Accept, Authorization"
           );
           if (req.method === "OPTIONS") {
               res.header(
                   "Access-Control-Allow-Methods",
                   "PUT, POST, PATCH, GET, DELETE"
               );
               return res.status(200).json({});
           } 
           next(); // send the request to the next middleware
       });
    }
}

export default new App().express;

Для использования файла app.ts

/**
* server.ts
*/
import * as http from "http";
import app from "./app";

const server: http.Server = http.createServer(app);

const PORT: any = process.env.PORT || 3000;
server.listen(PORT);
0 голосов
/ 14 июня 2018

Я выполнил следующие шаги в своем веб-приложении и добился успеха:

Добавьте пакет Cors к экспрессу:

npm install cors --save

Добавьте следующие строки после настройки bodyParser . У меня были некоторые проблемы с добавлением до bodyParser:

 // enable cors to the server
const corsOpt = {
    origin: process.env.CORS_ALLOW_ORIGIN || '*', // this work well to configure origin url in the server
    methods: ['GET', 'PUT', 'POST', 'DELETE', 'OPTIONS'], // to works well with web app, OPTIONS is required
    allowedHeaders: ['Content-Type', 'Authorization'] // allow json and token in the headers
};
app.use(cors(corsOpt)); // cors for all the routes of the application
app.options('*', cors(corsOpt)); // automatic cors gen for HTTP verbs in all routes, This can be redundant but I kept to be sure that will always work.
0 голосов
/ 15 мая 2016

Мы можем избежать CORS и перенаправить запросы на другой сервер:

// config:
var public_folder = __dirname + '/public'
var apiServerHost = 'http://other.server'

// code:
console.log("starting server...");

var express = require('express');
var app = express();
var request = require('request');

// serve static files
app.use(express.static(public_folder));

// if not found, serve from another server
app.use(function(req, res) {
    var url = apiServerHost + req.url;
    req.pipe(request(url)).pipe(res);
});

app.listen(80, function(){
    console.log("server ready");
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...