没有 ExpressJS 到本地服务器的“Access-Control-Allow-Origin”标头

Posted

技术标签:

【中文标题】没有 ExpressJS 到本地服务器的“Access-Control-Allow-Origin”标头【英文标题】:No 'Access-Control-Allow-Origin' header with ExpressJS to local server 【发布时间】:2017-01-02 03:56:02 【问题描述】:

我知道这个话题似乎已经回答了很多次了,但我真的不明白。

我有一个本地 angular-fullstack 应用程序(Express、NodeJs),它有他的 服务器 A (localhost:9000/)。 我有另一个本地 前台应用程序 B(BlurAdmin 已完成 生成器-gulp-angular) (localhost:3000/)

我的服务器 A 是使用 Express 和 Nodejs 自动生成的:

  app.use(function (req, res, next) 

    res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
    res.setHeader('Access-Control-Allow-Credentials', false);
    next();
);

在我的应用 B 中,对我的服务器 A 的 API 的 GET 请求有效

$http.get('http://localhost:9000/api/shows')

但是有一个 PUT 请求:

$http.put('http://localhost:9000/api/shows/1', object)

我有以下错误:

XMLHttpRequest 无法加载 http://localhost:9000/api/shows/1。不 请求中存在“Access-Control-Allow-Origin”标头 资源。因此不允许使用原点“http://localhost:3000” 使用权。响应的 HTTP 状态代码为 403。

我尝试:

  $http(
    method: "PUT",
    url:'http://localhost:9000/api/shows/1',
    headers: 
      'Content-type': 'application/json'
    ,
    data:object
  );

不工作,

我尝试:

res.header('Access-Control-Allow-Origin', '*');

不工作,

我已经为 chrome 安装了 *ExtensionAllow-Control-Allow-Origin: ** 并且什么也没做(不返回所有代码,只返回错误 403(禁止)

我真的不知道为什么当 PUT 与 GET 一起使用时,这对 PUT 不起作用。

您是否已经遇到过这个问题?谢谢!

更新:1 我的浏览器中的结果: 对于 GET

General:
Request URL:http://localhost:9000/api/shows/1
Request Method:OPTIONS
Status Code:200 OK

Request header:
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4,de-DE;q=0.2,de;q=0.2
Access-Control-Request-Headers:content-type
Access-Control-Request-Method:PUT
Connection:keep-alive
Host:localhost:9000
Origin:http://localhost:3000
Referer:http://localhost:3000/

Response header: 
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:X-Requested-With,content-type
Access-Control-Allow-Methods:GET, POST, OPTIONS, PUT, PATCH, DELETE
Access-Control-Allow-Origin:http://localhost:3000
Allow:GET,HEAD,PUT,PATCH,DELETE
Connection:keep-alive
Content-Length:25
Content-Type:text/html; charset=utf-8

对于 PUT 请求:

general:
Request URL:http://localhost:9000/api/shows/1
Request Method:PUT
Status Code:403 Forbidden

Response Header:
Connection:keep-alive
Content-Encoding:gzip
Content-Type:application/json; charset=utf-8
Date:Thu, 25 Aug 2016 16:29:44 GMT
set-cookie:connect.sid=s%3AsVwxxbO-rwLH-1IBZdFzZK1xTStkDUdw.xuvw41CVkFCRK2lHNlowAP9vYMUwoRfHtc4KiLqwlJk; Path=/; HttpOnly
set-cookie:XSRF-TOKEN=toaMLibU5zWu2CK19Dfi5W0k4k%2Fz7PYY%2B9Yeo%3D; Path=/
Strict-Transport-Security:max-age=31536000; includeSubDomains; preload

Request header:
Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4,de-DE;q=0.2,de;q=0.2
Connection:keep-alive
Content-Length:27
Content-Type:application/json
Host:localhost:9000
Origin:http://localhost:3000
Referer:http://localhost:3000/

Request Payload:
url_name: "myData"
url_name
:
"myData"

感谢您的帮助

更新 2: https://github.com/troygoode/node-cors-server/blob/master/app.js 和 @Chris Foster 的工作 我已经安装了npm cors --save 在我的 app.js 中, 我现在有以下代码:

import express from 'express'; 
import cors from 'cors'; 

var app = express()

var corsOptions = 
  origin: 'http://localhost:3000'

var issuesoption = 
  origin: true,
  methods: ['PUT'],
  credentials: true,
;


app.use(cors(corsOptions))
app.options('*', cors(issuesoption));
app.put('/api/shows/:id',cors(issuesoption) ,function(req,res)
  res.json(
    data: 'Issue #2 is fixed.'
  );
);

这仍然无法使用:

$http.put("http://localhost:9000/api/shows/1",object)

但是我没有任何 403 错误,我现在有,

Request URL:http://localhost:9000/api/shows/1
Request Method:PUT
Status Code:200 OK

但是没有将数据放入服务器并且我在预览中:

data: "Issue #2 is fixed."

【问题讨论】:

你是否在插件中启用了 cors(谷歌浏览器扩展)? 是的,启用跨域资源共享为真,当它被激活时,我只有错误:403(禁止) 你尝试重启浏览器了吗? 能否将 PUT 请求和 GET 请求的请求标头的完整列表包括在浏览器的网络开发工具中捕获的完整列表? @Wandrille 好的,所以如果没有实际的 POST 请求,那么预检请求就会失败。确保您的服务器也为预检发送适当的标头。 (GET 不需要预检请求。)您可能对我在How does Access-Control-Allow-Origin header work?的回答感兴趣 【参考方案1】:

当您发出可以更改某些内容的请求(POSTPUT 等)时,CORS 规则要求浏览器在发出实际请求之前发出 preflight request (OPTIONS)。

在 Node 中,您必须专门处理这些 OPTION 请求。您可能只处理PUT (app.put('/etc/etc/')),而预检请求失败。

您需要 add handling 进行预检 OPTION 请求,但最好查看 cors 包,它可以让这一切变得更加简单并为您完成:

const express = require('express')
const cors = require('cors')

const app = express()

const corsOptions = 
  origin: 'http://example.com'


app.use(cors(corsOptions))

【讨论】:

@Wandrille 此代码确实解决了您的问题,事实上您现在看到 200 OK 意味着请求有效 :) 您在预览中看到的 JSON 正是路由的设计目的:将 JSON 发送到客户端。它不会对你发送的数据做任何事情,因为你还没有编写路由来做任何事情。 像您提到的那样“将数据放入服务器”,这是一个不同的问题。您必须使用req.bodybodyParser 中间件(如this question 中提到的)处理客户端在路由处理程序中发送给您的数据。如果在那之后您需要更多帮助,您应该打开一个新问题,因为它与 CORS 问题无关。祝你好运! 我只尝试了你的代码,但我一直遇到问题。谢谢:) 让我们continue this discussion in chat。 确保在创建 express 应用程序后立即添加此中间件,然后再添加其他中间件,在我这样做之前最初对我不起作用。

以上是关于没有 ExpressJS 到本地服务器的“Access-Control-Allow-Origin”标头的主要内容,如果未能解决你的问题,请参考以下文章

将 ReactJS 和 ExpressJS 部署到 Nginx

如何允许无限制的发布请求 expressjs

expressjs http 不适用于 spdy

从 expressJS (sendFile) 服务器下载文件到 VueJS,是不是返回损坏的文件?

如何诊断/调试 nodejs/expressjs 的 500 内部服务器错误?

ExpressJS / Angular 2 JWT 令牌