我正在尝试使用 json-server、Node 和 Express 在 localhost 上为我的 Angular 应用程序模拟 RESTFUL API。随之而来的 CORS 问题

Posted

技术标签:

【中文标题】我正在尝试使用 json-server、Node 和 Express 在 localhost 上为我的 Angular 应用程序模拟 RESTFUL API。随之而来的 CORS 问题【英文标题】:I'm attempting to use json-server, Node, and Express to mock a RESTFUL API for my Angular app on localhost. CORS issues have ensued 【发布时间】:2015-07-02 14:14:40 【问题描述】:

基本上,我需要使用 json-server 运行 Node/Express 服务器来模拟我正在开发的测试 Angular 应用程序的 RESTFUL API。问题是谷歌浏览器抛出一个错误,表明我遇到了 CORS 问题。我尝试以解决 CORS 问题的方式配置我的服务器。 . .

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

。 . .无济于事。

在不摆弄 JSONP 或以任何方式更改我的 Angular 代码的情况下,我还能做些什么吗?它似乎在 Rails 服务器上运行良好。

编辑:正如许多人所建议的那样,我尝试使用 cors 模块来解决这个问题,但这似乎也不起作用。这是我的 server.js 文件:

var express = require('express');
var app = express();
var path = require("path");
var jsonServer = require("json-server");
var databaseServer = jsonServer.create();
var cors = require("cors");

app.use(cors());
app.use("/", express.static(__dirname));
  var server = app.listen(3000, function () 
  var host = server.address().address;
  var port = server.address().port;
  console.log('Example app listening at http://%s:%s', host, port);
);

var object = 
  "fighters": [
    
      "id": 1,
      "firstName": "Jose",
      "lastName": "Aldo",
      "nickname": "Scarface",
      "wins": 25,
      "losses": 1,
      "draws": 0,
      "imageUrl": "/images/jose_aldo.png"
    ,
    
      "id": 2,
      "firstName": "Conor",
      "lastName": "McGregor",
      "nickname": "",
      "wins": 17,
      "losses": 2,
      "draws": 0,
      "imageUrl": "/images/conor_mcgregor.png"
    
  ]
;


databaseServer.use(jsonServer.defaults);
databaseServer.use(jsonServer.router(object));
databaseServer.listen(4000);

这是我的 Angular 服务:

var FighterService = angular.module("FighterService", ["ngResource"]);

FighterService.factory("Fighter", ["$resource", function ($resource) 
  return $resource("localhost:4000/fighters/:fighterId",
     fighterId : "@id" ,
    
      query: 
        method: "GET",
        params:  fighterId: "@id" ,
        isArray: true 
      ,
      get:  method: "GET" 
    );
]);

【问题讨论】:

Chrome 给你的具体错误是什么? XMLHttpRequest 无法加载 localhost:4000/fighters.json。跨源请求仅支持协议方案:http、data、chrome、chrome-extension、https、chrome-extension-resource.b @ angular.js:9866。 . . 您的 Angular 应用程序是否由同一台服务器托管? 没有。我不知道如何设置它,以便数据库和应用程序都从同一台服务器提供服务。我已经在上面添加了我的服务器文件。 【参考方案1】:

已解决

线索在错误中:

XMLHttpRequest 无法加载 localhost:4000/fighters.json。跨源请求仅支持协议方案:http、data、chrome、chrome-extension、https、chrome-extension-resource.b

在你的 Angular 中,一行

return $resource("localhost:4000/fighters/:fighterId",

认为您指的是使用协议“localhost:”的 URL。

它应该是一个绝对的 HTTP URL:

return $resource("http://localhost:4000/fighters/:fighterId",

有了你已经拥有的正确 CORS 支持,它就可以工作。

【讨论】:

【参考方案2】:

如果您使用 Json-Server 来提供您的 api,您可以禁用 Cors

查看 json-server 文档https://github.com/typicode/json-server。

本质上,json-server 中间件默认为noCors: false

我认为您可以更改它并将其设置为noCors: true

可能是这样的:

const server = jsonServer.create();
const middlewares = jsonServer.defaults( noCors: true )

// set default middlewares (logger, static, cors and no-cache)
server.use(middlewares);

【讨论】:

【参考方案3】:

如果你想在 Express 上使用 CORS,你需要启用 cors 并配置

var cors = require('cors');

var whitelist = [
  'http://localhost', // add here the url when you access to your angular app
  'http://localhost:8080',
  'http://otherdomain.com'
];

var corsOptions = 
    credentials: true,
    origin: function(origin, callback) 
        var originIsWhitelisted = whitelist.indexOf(origin) !== -1;
        callback(null, originIsWhitelisted);
    ,
    methods: ['GET', 'PUT', 'POST', 'PATCH', 'DELETE'],
    allowedHeaders: 'accept, content-type'
;

app.use(cors(corsOptions));

例如,我在 3000 端口上运行 express 服务器并且我的应用程序可以在端口 8080 上运行并且工作正常,或者我的应用程序可以在 http://otherdomain.com 上运行并且也可以工作。

【讨论】:

我使用过app.use(auth);const auth = require("json-server-auth");,如何添加自定义cors 设置标题以允许标题【参考方案4】:

如果只有您需要进行测试,最简单的方法可能是使用--disable-web-security 打开 Chrome,这样浏览器就不需要 CORS 标头来将数据视为安全。 (h/t @Taran)

如果其他人也需要测试,最简单的方法可能是使用the cors module。

如果您想使用自己的 Express 中间件来处理它,我前段时间也做过同样的事情。这就是我想出的。用这个替换你上面的 Express 中间件:

app.use(function (req, res, next) 
    'use strict';

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

    if (req.headers['access-control-request-method']) 
        res.header('Access-Control-Allow-Methods', 'GET, OPTIONS');
    
    if (req.headers['access-control-request-headers']) 
        res.header('Access-Control-Allow-Headers', 'X-Requested-With');
    

    res.header('Access-Control-Max-Age', 60 * 60 * 24 * 365);

    if (req.method === 'OPTIONS') 
        res.sendStatus(200);
     else  
        next();
    
);

如果您需要更多上下文,代码是here。

【讨论】:

是的。我已经用我的服务器端代码更新了我的原始帖子。【参考方案5】:

如果只是为了测试,您可以通过 --disable-web-security 开关启动 Chome 来告诉 Chome 接受 CORS。

【讨论】:

【参考方案6】:

您需要通过在您的 express 应用中添加 cors 模块来启用 cors。使用npm 命令下载其依赖项。 并在您的 node.js 文件中添加以下行。

var cors = require('cors');

app.use(cors());

【讨论】:

@MichaelP。您已在服务器端节点文件中添加了这些行吗? 请看一下这个。您正在尝试打开文件,这就是发生协议错误的原因。 ***.com/questions/27742070/… 看。 . .如果你不介意,请站在一边。这可能是解决方案。 :-D 好的。我不确定这如何解决问题。我看到它会给我另一个服务器,但我不确定它如何让我绕过 CORS 问题。 确保您的 fighters.json 文件位于您的节点服务器项目中?【参考方案7】:

在我看来(眯起眼睛)你应该能够通过模拟服务器为你提供 Angular 应用程序并解决你的问题..

- app.use("/", express.static(__dirname)); 
+ app.use("/angular_app", express.static(__dirname));

然后将您的 Angular 应用程序目录链接到运行模拟服务器的 /angular_app。

ln -s angular/app ../mock/angular_app

您应该能够在 localhost:4000/(或者是 :3000?)访问您的 Angular 应用程序

【讨论】:

以上是关于我正在尝试使用 json-server、Node 和 Express 在 localhost 上为我的 Angular 应用程序模拟 RESTFUL API。随之而来的 CORS 问题的主要内容,如果未能解决你的问题,请参考以下文章

json-server在发布请求后出现错误

JSON-Server:使用参数模拟端点

无法在 JSON-SERVER 中执行 CRUD

使用 JWT 对 json-server 进行授权

无法使用 json-server 并一起做出反应

使用 json-server 和 React.js 进行分页