将CORS标头添加到Angular 6中的响应

时间:2018-12-04 08:10:52

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

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

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

此外,为了防止发表任何评论,我所获得的所有数据我都有合法的访问权限,它们是我自己的,我只是在学习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'
      }
    );
  }

我写的Interceptor类:

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内部使用它在documentation中。我仍然缺少一些东西。

3 个答案:

答案 0 :(得分:1)

它不能那样工作。 Cors是在服务器端处理的东西。 Serveradministrator设置这些标头并允许某些域的位置。您应该考虑使用JsonP,或者如果您说过要控制数据,则可以考虑允许服务器上的域。这些是Acces Control Allow Headers

答案 1 :(得分:0)

在向服务器发出的跨源HTTP请求中包含诸如 Authorization 之类的某些标头时,浏览器通常会进行 OPTIONS 飞行前 >)向服务器发出请求,要求提供允许的 Access-Control-Allow-Methods 和允许的 Access-Control-Allow-Headers ,您的服务器端代码应对此做出回应浏览器实际发出您想要的http请求

答案 2 :(得分:0)

您无需为请求设置标题。为了避免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": "/"
  }
 }
}

只需很少修改即可更改serve命令:

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

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

注意:此Proxy配置仅用于开发目的。对于生产环境,应该在Web服务器中进行配置。