【问题标题】:Add CORS header to response in Angular 6在 Angular 6 中将 CORS 标头添加到响应中
【发布时间】:2019-05-05 14:37:03
【问题描述】:

我正在尝试从 Angular 6 中的后端服务器获取一些数据,以便以我自己的方式对其进行可视化。我已经准备了一个有效的 GET 请求,它可以对我需要的所有数据做出正确的响应,但问题是当它以典型方式使用时,例如在“普通”浏览器中,我收到了 CORS 错误 -标题丢失。那么即使有这个问题,我如何获取数据呢?通常,您必须在服务器端允许它,但这种情况有点不同。我已经安装了一个 Chrome 插件来为每个请求添加标题。有了这个插件,CORS 问题就不复存在了。

所以我的问题是,如何(以及是否)将我的 Angular 代码中的 CORS 标头添加到响应中,这样我就不必使用任何插件,并且该应用程序可以在每个浏览器上运行?

另外,为了防止任何 cmets,我获得的所有数据都是我可以合法访问的,它们是我自己的,我只是在 Angular 中学习新东西。据我所知,我应该使用拦截器,但我很确定我做错了。这是我的代码:

http服务方式:

  getFullResponse(domain: string, projectName: string, credentials: Credentials) {
    console.log('RequestService method getIssuesForProject() fired');

    return this.http.get('https://' + domain + '.myserver.local/api/' + projectName,
      {
        headers: new HttpHeaders({'Authorization': 'Basic ' + btoa(credentials.username + ':' + credentials.password)}),
        observe: 'response'
      }
    );
  }

我写的拦截器类:

import {Injectable} from '@angular/core';
import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse} from '@angular/common/http';
import {Observable} from 'rxjs';
import {map} from 'rxjs/operators';

@Injectable()
export class ResponseInterceptor implements HttpInterceptor {

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req).pipe(
      map(event => {
        if (event instanceof HttpResponse) {
          event = event.clone({
            headers: event.headers.set('Access-Control-Allow-Origin', '*')
          });
        }
        return event;
      })
    );
  }

}

这是 component.ts 类:

import {Component, OnInit} from '@angular/core';
import {RequestService} from '../../shared/service/RequestService.service';
import {Credentials} from '../../shared/model/credentials';

@Component({
  selector: 'app-project',
  templateUrl: './project.component.html',
  styleUrls: ['./project.component.css']
})
export class ProjectComponent implements OnInit {

  projectKey = '';
  headers;
  credentials: Credentials;

  constructor(private reqService: RequestService) {
  }

  ngOnInit() {
  }

  onSubmit(domainName: string, projectKey: string, user: string, password: string) {
    this.projectKey = projectKey;
    this.credentials = {
      username: user,
      password: password
    };
    this.reqService.getFullResponse(domainName, projectKey, this.credentials)
      .subscribe(resp => {
        const keys = resp.headers.keys();
        this.headers = keys.map(key => `${key}: ${resp.headers.get(key)}`);
      });
  }

}

我尝试使用 app.module.ts 以 link 下的方式使用拦截器。这完全破坏了我的应用程序,因为即使打开了 CORS 插件,我也会收到 CORS 错误。我在互联网上找到的其他代码示例使用了类似

的代码
return next.handle(reqClone) 
       .map(event => { 
         if (event instanceof HttpResponse) { 
           event = event.clone({ 
             headers: event.headers.set('x-test-res', 'res-test-header') 
           }); 
         } 
         return event; 
}); 

在拦截器中,但我猜它是针对旧版本的 Angular,我不能以这种方式使用 map 方法,所以我尝试在 pipe 中使用它,就像在 @987654322 中使用它一样@。不过,我仍然缺少一些东西。

【问题讨论】:

    标签: angular rest cors http-headers angular-http-interceptors


    【解决方案1】:

    它不是那样工作的。 Cors 是在服务器端处理的东西。服务器管理员设置这些标头并允许某些域的位置。您应该适当地查看JsonP,或者如果您像您所说的那样控制数据,请查看允许您的域在您的服务器上。这些是Acces Control Allow Headers

    【讨论】:

    • 我知道 CORS 是什么以及它是如何工作的,但我想知道我是否可以使用 Angular 实现与 Chrome 插件相同的效果,它仍然允许我通过添加标题来查看数据。
    • 这个类似的帖子可能会有所帮助:stackoverflow.com/questions/36250615/cors-with-postman
    • 是的。所以目前看来,Angular 无法做到这一点,因为我必须修改 Web 浏览器的行为,而 Web 应用程序无法做到这一点......
    • @Jack_Russell 浏览器负责限制 Web 应用访问跨域服务器。只有通过安装插件,您才能更改此行为。不允许网络应用程序更改这一点,因为如果可以,那么拥有 CORS 将毫无意义。
    【解决方案2】:

    当您在向服务器发出的跨源 http 请求中包含某些标头(例如 Authorization)时,浏览器通常会发出 OPTIONSpre flight >) 向服务器请求允许的 Access-Control-Allow-Methods 和允许的 Access-Control-Allow-Headers,您的服务器端代码应使用这些响应浏览器实际发出您想要的 http 请求

    【讨论】:

      【解决方案3】:

      您不需要为请求设置标头。为了避免 Angular 中的 CORS 错误,您应该使用 proxy pass 配置进行开发。

      package.json 附近添加一个名为 proxy.conf.json 的文件。从您的请求获取 URL 添加 /proxy

       this.http.get('/proxy/api/' + 
        projectName).subscribe(resData => {
              console.log(resData);
        });
      

      proxy.conf.json中设置代理规则为

      {
        "/proxy/*": {
        "target": "http://backendDomain:8080",
        "secure": false,
        "logLevel": "debug",
        "changeOrigin": true,
        "pathRewrite": {
        "^/proxy": "/"
        }
       }
      }
      

      只需稍加修改即可更改服务命令:

      ng serve --proxy-config proxy.conf.json --port 55055 --host 0.0.0.0
      

      现在对后端的请求将来自相同的角度域,不会再有 CORS 错误

      注意:此代理配置仅用于开发目的。对于生产环境你应该在 webservers 中配置。

      【讨论】:

      • 问题是,REST API 所在的地址是远程的。我也尝试通过 Nginx 代理请求,但我对此完全陌生。由于邮递员请求有效,我想知道是否有办法从我的应用程序发送请求,就好像它是邮递员请求一样,但是这里有些东西不正确,现在我完全迷路了
      猜你喜欢
      • 2016-05-15
      • 2019-09-05
      • 2018-11-15
      • 2020-03-16
      • 2019-01-30
      • 2020-02-10
      • 2021-11-08
      • 2016-07-25
      • 1970-01-01
      相关资源
      最近更新 更多