Как разрешить CORS?
Я пытаюсь поддерживать 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?
39 ответов
Чтобы ответить на ваш главный вопрос, спецификация CORS требует, чтобы вызов OPTIONS предшествовал POST или GET, если в POST или GET есть непростой контент или заголовки.
Типы контента, для которых требуется предполетный запрос CORS (вызов OPTIONS), это любой тип контента, кроме следующих:
application/x-www-form-urlencoded
multipart/form-data
text/plain
Любые другие типы контента, кроме перечисленных выше, вызовут предполетный запрос.
Что касается Заголовков, любые Заголовки Запроса кроме следующего вызовут предполетный запрос:
Accept
Accept-Language
Content-Language
Content-Type
DPR
Save-Data
Viewport-Width
Width
Любые другие заголовки запроса активируют предполетный запрос.
Таким образом, вы можете добавить собственный заголовок, такой как: x-Trigger: CORS
и это должно вызвать предполетный запрос и попасть в блок OPTIONS.
См. Справочник по MDN Web API - Предварительные запросы CORS.
Я обнаружил, что самый простой способ - использовать пакет cors для node.js. Самое простое использование:
var cors = require('cors')
var app = express()
app.use(cors())
Есть, конечно, много способов настроить поведение в соответствии с вашими потребностями; на странице, указанной выше, приведено несколько примеров.
Попробуйте передать управление следующему подходящему маршруту. Если Express сначала совпадает с маршрутом app.get, он не продолжит движение по маршруту параметров, если вы не сделаете это (обратите внимание на использование next):
app.get('somethingelse', function(req, res, next) {
//..set headers etc.
next();
});
Что касается организации CORS, я поместил ее в промежуточное ПО, которое хорошо работает для меня:
//CORS middleware
var allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', 'example.com');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
}
//...
app.configure(function() {
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({ secret: 'cool beans' }));
app.use(express.methodOverride());
app.use(allowCrossDomain);
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
Чтобы остаться в той же идее маршрутизации. Я использую этот код:
app.all('/*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
next();
});
Аналогично примеру http://enable-cors.org/server_expressjs.html
Делать
npm install cors --save
и просто добавьте эти строки в ваш основной файл, куда направляется ваш запрос (сохраните его перед любым маршрутом).
const cors = require('cors');
const express = require('express');
let app = express();
app.use(cors());
app.options('*', cors());
Я сделал более полное промежуточное программное обеспечение, подходящее для экспресс или подключения. Поддерживает OPTIONS
запросы на предполетную проверку. Обратите внимание, что это разрешит CORS доступ ко всему, вы можете захотеть поставить некоторые проверки, если хотите ограничить доступ.
app.use(function(req, res, next) {
var oneof = false;
if(req.headers.origin) {
res.header('Access-Control-Allow-Origin', req.headers.origin);
oneof = true;
}
if(req.headers['access-control-request-method']) {
res.header('Access-Control-Allow-Methods', req.headers['access-control-request-method']);
oneof = true;
}
if(req.headers['access-control-request-headers']) {
res.header('Access-Control-Allow-Headers', req.headers['access-control-request-headers']);
oneof = true;
}
if(oneof) {
res.header('Access-Control-Max-Age', 60 * 60 * 24 * 365);
}
// intercept OPTIONS method
if (oneof && req.method == 'OPTIONS') {
res.send(200);
}
else {
next();
}
});
Сделайте что-то вроде этого:
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
Установить модуль Cors ExpressJS. Вы можете выполнить следующие действия>
Монтаж
npm install cors
Простое использование (включить все запросы CORS)
var express = require('express');
var cors = require('cors');
var app = express();
app.use(cors());
для получения более подробной информации перейдите на https://github.com/expressjs/cors
Тестирование выполнено с экспресс + узел + ионный работает в разных портах.
Localhost:8100
Localhost:5000
// CORS (Cross-Origin Resource Sharing) headers to support Cross-site HTTP requests
app.all('*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
});
Сначала просто установите Cors в вашем проекте. Возьмите терминал (командную строку) и cd
в каталог вашего проекта и выполните следующую команду:
npm install cors --save
Затем возьмите файл server.js и измените код, добавив в него следующее:
var cors = require('cors');
var app = express();
app.use(cors());
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'DELETE, PUT, GET, POST');
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
Это сработало для меня..
Некоторое время назад я столкнулся с этой проблемой, поэтому я сделал это, чтобы включить CORS в моем приложении nodejs:
Сначала вам нужно установить cors
используя следующую команду:
npm install cors --save
Теперь добавьте следующий код в стартовый файл вашего приложения, как (app.js or server.js
)
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
}));
require('./router/index')(app);
Это работает для меня, так как это простая реализация внутри маршрутов, я использую Meanjs и его работает нормально, Safari, Chrome и т. Д.
app.route('/footer-contact-form').post(emailer.sendFooterMail).options(function(req,res,next){
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, POST');
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
return res.send(200);
});
Если вы хотите сделать его специфичным для контроллера, вы можете использовать:
res.setHeader('X-Frame-Options', 'ALLOWALL');
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'POST, GET');
res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
Пожалуйста, обратите внимание, что это также позволит использовать iframes.
В моем index.js
Я добавил:
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
next();
})
cors
package - рекомендуемый способ решения проблемы политики CORS в express.js, но вам также необходимо включить его для
app.options
а также, как показано ниже:
const cors = require('cors');
// enable cors
app.use(
cors({
origin: true,
optionsSuccessStatus: 200,
credentials: true,
})
);
app.options(
'*',
cors({
origin: true,
optionsSuccessStatus: 200,
credentials: true,
})
);
Самый простой ответ - просто использовать пакет cors.
const cors = require('cors');
const app = require('express')();
app.use(cors());
Это позволит использовать CORS по всем направлениям. Если вы хотите узнать, как включить CORS без внешних модулей, все, что вам действительно нужно, это некоторое промежуточное программное обеспечение Express, которое устанавливает заголовок Access-Control-Allow-Origin. Это минимум, который вам нужен, чтобы разрешить перекрестные запросы доменов из браузера на ваш сервер.
app.options('*', (req, res) => {
res.set('Access-Control-Allow-Origin', '*');
res.send('ok');
});
app.use((req, res) => {
res.set('Access-Control-Allow-Origin', '*');
});
Можете сослаться на код ниже для того же. Источник: Academind / node-restful-api
const express = require('express');
const app = express();
//acts as a middleware
//to handle CORS Errors
app.use((req, res, next) => { //doesn't send response just adjusts it
res.header("Access-Control-Allow-Origin", "*") //* to give access to any origin
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept, Authorization" //to give access to all the headers provided
);
if(req.method === 'OPTIONS'){
res.header('Access-Control-Allow-Methods', 'PUT, POST, PATCH, DELETE, GET'); //to give access to all the methods provided
return res.status(200).json({});
}
next(); //so that other routes can take over
})
Ниже работал для меня, надеюсь, это поможет кому-то!
const express = require('express');
const cors = require('cors');
let app = express();
app.use(cors({ origin: true }));
Получил ссылку с https://expressjs.com/en/resources/middleware/cors.html
Мое простейшее решение с Express 4.2.0 (EDIT: кажется, не работает в 4.3.0) было:
function supportCrossOriginScript(req, res, next) {
res.status(200);
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Content-Type");
// res.header("Access-Control-Allow-Headers", "Origin");
// res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
// res.header("Access-Control-Allow-Methods","POST, OPTIONS");
// res.header("Access-Control-Allow-Methods","POST, GET, OPTIONS, DELETE, PUT, HEAD");
// res.header("Access-Control-Max-Age","1728000");
next();
}
// Support CORS
app.options('/result', supportCrossOriginScript);
app.post('/result', supportCrossOriginScript, function(req, res) {
res.send('received');
// do stuff with req
});
Я полагаю app.all('/result', ...)
будет работать тоже...
В дополнение к тому, что сказали другие, не забывайте, что если вы не используете nodemon, вам нужно будет перезапустить сервер вашего узла, чтобы изменения вступили в силу!
Я лично по привычке обновлял свой браузер, забывая, что это код на стороне сервера.
С помощью
CORS
пакет. и поставьте эти параметры:
cors({credentials: true, origin: true, exposedHeaders: '*'})
Попробуйте это в своем основном файле js:
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header(
"Access-Control-Allow-Headers",
"Authorization, X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Allow-Request-Method"
);
res.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, DELETE");
res.header("Allow", "GET, POST, OPTIONS, PUT, DELETE");
next();
});
Это должно решить вашу проблему
Если вы хотите, чтобы CORS работал без пакета cors NPM (для чистого удовольствия от обучения!), Вы определенно можете самостоятельно обрабатывать вызовы OPTIONS. Вот что у меня сработало:
app.options('*', (req, res) => {
res.writeHead(200, '', {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'OPTIONS',
}).end();
});
Красиво и просто, правда? Обратите внимание на использование res.writeHead () вместо res.header (), с которым я не знаком.
В машинописи, если вы хотите использовать cors пакета node.js
/**
* 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);
Если на вашем экспресс-сервере включена авторизация, вы можете добиться этого следующим образом .
const express = require('express');
const app=express();
const cors=require("cors");
app.use(cors({
credentials: true, // for authorization
}));
...
Я обнаружил, что это очень легко сделать с помощью пакета запросов 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'));
});
Это похоже на ответ Пата с той разницей, что я заканчиваю с res.sendStatus(200); вместо следующего ();
Код будет перехватывать все запросы типа метода OPTIONS и отправлять обратно заголовки контроля доступа.
app.options('/*', (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');
res.sendStatus(200);
});
Код принимает CORS из всех источников в соответствии с запросом в вопросе. Тем не менее, было бы лучше заменить * конкретным источником, то есть http://localhost:8080/, чтобы предотвратить неправильное использование.
Поскольку мы используем метод app.options вместо метода app.use, нам не нужно выполнять эту проверку:
req.method === 'OPTIONS'
который мы можем увидеть в некоторых других ответах.
Я нашел ответ здесь: http://johnzhang.io/options-request-in-express.
Использование Express Middleware прекрасно работает для меня. Если вы уже используете Express, просто добавьте следующие правила промежуточного программного обеспечения. Это должно начать работать.
app.all("/api/*", function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Cache-Control, Pragma, Origin, Authorization, Content-Type, X-Requested-With");
res.header("Access-Control-Allow-Methods", "GET, PUT, POST");
return next();
});
app.all("/api/*", function(req, res, next) {
if (req.method.toLowerCase() !== "options") {
return next();
}
return res.send(204);
});
Мы можем избежать 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");
});
Самый простой подход - установить модуль Cors в ваш проект, используя:
npm i --save cors
Затем в файл вашего сервера импортируйте его, используя следующее:
import cors from 'cors';
Затем просто используйте его в качестве промежуточного ПО, например:
app.use(cors());
Надеюсь это поможет!