【问题标题】:Minimum Node+Express+TypeScript With Angular. I got "CORS policy" problem最小的 Node+Express+TypeScript 与 Angular。我遇到了“CORS 政策”问题
【发布时间】:2019-01-30 00:13:40
【问题描述】:

我是这个领域的新手。我从本地的Node+Typescript 示例开始。听代码:

import express from 'express';
const app = express();

var counter: number=0;

app.get('/', (req, res) => {res.send('Hello World! ${counter}' + counter.toString()); counter++;} );

app.listen(3000, () => console.log('Example app listening on port 3000!'));

我还为客户端编写了一些 Angular 代码:

@Component({
  selector: 'test',
  template: '<div>Simple Http: {{counter}}</div><button (click)="onClickMe()">Click me!</button>'  
})
export class test {
  counter: any="Not yet";

  constructor(private http: HttpClient) { } 

  onClickMe() {
    this.counter = 'Try read from server..';
    this.http.get("http://localhost:3000/").subscribe(val=>this.counter=val);
  }
}

我通过 npm 运行客户端:“ng serve”http://localhost:4200/

我收到错误:

从源访问“http://localhost:3000/”处的 XMLHttpRequest 'http://localhost:4200' 已被 CORS 策略阻止:否 请求中存在“Access-Control-Allow-Origin”标头 资源。

我知道有一个名为“cors”的库。但我不确定如何使用 Typescript 安装它或如何使用它。

【问题讨论】:

    标签: node.js typescript


    【解决方案1】:

    谢谢大家。我添加了 Angule+Node+Express 的固定最小代码和指令,用于通过 HttpClient 获取数据。我写得尽量简单。

    服务器代码(基于Node+Express starter

    import express from 'express';    
    import cors from 'cors';
    
    const app = express();
    
    var counter: number=0;
    
    app.get('/', cors() ,(req, res) => {res.json({ counter: `${counter}`}); counter++;} );
    
    app.listen(3000, () => console.log('Example app listening on port 3000!'));
    

    注意,你应该安装cors:

    npm install cors
    

    您可能还想为它安装类型脚本(不是必需的)

    npm install @types/cors
    

    现在,构建并运行节点项目:

    npm run-script build
    npm start 
    

    现在将以下代码添加到您的 Angular 项目中:

    import { Component } from '@angular/core';
    import { HttpClient, HttpHandler, HttpRequest, HttpEvent } from '@angular/common/http';
    
    
    @Component({
      selector: 'TestHttp',
      template: '<div>Simple Http: {{counter}}</div><button (click)="onClickMe()">Click me!</button>'  
    })
    export class TestHttp {
      counter: number=null;
    
    
      constructor(private http: HttpClient) { } 
    
      onClickMe() {
        this.counter = -1;        
        let obs: any = this.http.get("http://localhost:3000/");
        obs.subscribe(val=>this.counter=val['counter']);
      }
    }
    

    如您所见,此示例从视图组件中调用 http。这是错误的模式。但它展示了在服务器上使用 Http 是多么简单。

    此外,此示例不直接与 Injectable 或 Observable (rxjs) 一起使用。甚至不使用管道函数来检索数据。它只是通过添加它作为构造函数参数来注入HttpClient,并在app.module.ts中添加提供:

    providers: [HttpClient]
    

    【讨论】:

      【解决方案2】:

      您必须在服务器端配置和启用cors,在这种情况下,在 NodeJs 中。在Express docs 中,您有一个完整的教程,说明如何使用 Express 执行此操作。很简单:

      1. 安装corsnpm install cors
      2. var cors = require('cors') 在你的index.js 文件中实例化cors
      3. 最后,使用app.use(cors())cors 应用到您的整个API

      文档中有很多选项和配置,请查看!

      希望对你有帮助!

      【讨论】:

      • 好的,我做到了。但现在我在客户端遇到另一个错误:ERROR HttpErrorResponse {headers: HttpHeaders, status: 200, statusText: "OK", url: "localhost:3000", ok: false, ...}。
      • @MatanyaCohen 正如您所说,响应为您提供OK 和状态200,因此您在客户端处理响应时可能会遇到问题。你能提供更多细节吗?如果您在导航器中访问localhost:3000/,它会显示您Hello World! 0吗?
      • 实际上浏览器上的结果是:"Hello World!00" 没有错误。
      • 谢谢。现在我意识到问题是响应类型之间的不兼容。服务器返回文本/HTML,而 Angular 尝试将其读取为 Json。所以解决方案在服务器上: app.get('/', cors() ,(req, res) => {res.json({ counter: ${counter}}); counter++;} );
      • 问题是,为什么当客户端读取响应时我没有收到转换错误?
      【解决方案3】:

      或者你可以在没有cors 库的情况下做到这一点。 只需在中间件中设置标头即可:

      app.use(function(req, res, next) {
          res.header("Access-Control-Allow-Origin", '*');
          res.header("Access-Control-Allow-Credentials", true);
          res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
          res.header("Access-Control-Allow-Headers", 'Origin,X-Requested-With,Content-Type,Accept,content-type,application/json');
          next();
      });
      

      因此您在服务器上的代码将如下所示:

      import express from 'express';
      const app = express();
      
      var counter: number=0;
      
      app.use(function(req, res, next) {
          res.header("Access-Control-Allow-Origin", '*');
          res.header("Access-Control-Allow-Credentials", true);
          res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
          res.header("Access-Control-Allow-Headers", 'Origin,X-Requested-With,Content-Type,Accept,content-type,application/json');
          next();
      });
      
      app.get('/', (req, res) => {res.send('Hello World! ${counter}' + counter.toString()); counter++;} );
      
      app.listen(3000, () => console.log('Example app listening on port 3000!'));
      
      

      收到CORS 警告的原因是,出于安全原因,您的服务器不应允许将数据传输到其他网站(在您的情况下,它是两个不同的端口,它们完全是两个不同的网站)

      您可以在此处阅读更多信息:https://www.html5rocks.com/en/tutorials/cors/#toc-introduction

      Why does my JavaScript get a "No 'Access-Control-Allow-Origin' header is present on the requested resource" error when Postman does not?

      【讨论】:

      • @grooveplex 不知道,这是一个没有库的解决方案,也可以正常工作
      • 有两台服务器。一个服务于 Angular,第二个服务于数据。你确定我只需要处理数据(端口:3000)吗?
      • @MatanyaCohen,当然,有两台服务器。您需要深入了解并了解为什么会出现 CORS 问题。这是因为 HTTP CORS 策略中的安全原因。我会用一些链接更新我的答案
      猜你喜欢
      • 2020-12-23
      • 2020-03-30
      • 2020-01-15
      • 2021-06-24
      • 1970-01-01
      • 2019-03-26
      • 2020-05-20
      • 1970-01-01
      • 2023-03-08
      相关资源
      最近更新 更多