-2

I'm trying to fetch some data from a backend server in Angular 6 so I can visualize it in my own way. I've already prepared a working GET request that results in a proper response with all the data I need, but the problem is that when it's used in a typical way, e.g in "normal" browser, I'm getting the CORS error - header is missing. So how do I get the data even with this problem? Typically, you must allow it on the server side, but this situation is a bit different. I've installed a Chrome plugin to add the header to every request. With the plugin, the CORS problem is no more.

So my question is, how (and if) can I add the CORS header in my Angular code to the response, so I wouldn't have to use any plugins and the app would work on every browser?

Also, just to prevent any comments, all the data I'm getting I have legal access to, they're my own and I'm just learning new stuff in Angular. As far as I know, I should use interceptors, but I'm pretty sure I'm doing it wrong. Here's my code:

The http service method:

  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'
      }
    );
  }

The Interceptor class I wrote:

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

}

This is the component.ts class:

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)}`);
      });
  }

}

I've tried to use the Interceptor the way under this link, using the app.module.ts. This totally broke my app because I'm getting the CORS error even with the CORS plugin turned on. The other examples of code I found over the internet used code like

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

in the interceptor, but I'm guessing it's for older versions of Angular, I can't use the map method this way, so I tried using it inside of pipe like it was used in the documentation. There's still something I'm missing though.

Jack_Russell
  • 323
  • 5
  • 20

3 Answers3

2

It doesnt work like that. Cors is somehing that is handled serverside. Where the Serveradministrator sets those headers and allows certain domains. You should propably look into JsonP or if you have like you said control over the data look into allowing your domain on your server. Those are the Acces Control Allow Headers

Nikolai Kiefer
  • 568
  • 5
  • 15
  • I know what CORS is and how it works, but I'm asking if I can achieve the same effect with Angular as the Chrome plugin that still allows me to see the data just by adding the header. – Jack_Russell Dec 04 '18 at 08:35
  • 1
    This similar post may be helpful: https://stackoverflow.com/questions/36250615/cors-with-postman – DeborahK Dec 04 '18 at 08:46
  • yes, it is. so for now it looks like there's no way to do this with Angular, because I have to modify the behavior of web browser which cannot be done by a web application... – Jack_Russell Dec 04 '18 at 09:05
  • @Jack_Russell The browser is responsible for restricting web apps from accessing cross-origin servers. Only by installing a plugin you can change this behavior. Web apps aren't allowed to change that, because if the could, there would be no point in having CORS. – ShamPooSham Dec 04 '18 at 09:16
0

When you include certain headers like Authorization in your cross origin http request made to the server, browsers would generally make an OPTIONS(pre flight) request to the server asking for allowed Access-Control-Allow-Methods and allowed Access-Control-Allow-Headers, Your Server side code should respond with these for the browser to actually make your intended http request

Pushpendra
  • 1,694
  • 14
  • 27
0

You don't need to set Headers for the request. In order to avoid the CORS error in Angular you should use proxy pass configuration for development purpose.

add a file named proxy.conf.json near the package.json. from your Request get URL add /proxy

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

In the proxy.conf.json set the proxy rule as

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

change the serve command with little modification:

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

Now the request to the backend will be originated from the same from angular domain and there will be no more CORS error

Note : This Proxy configuration in only for the development purpose. For the production environment You should configure in the webservers.

esakki
  • 153
  • 1
  • 9
  • problem is, the address where the REST API is located, is a remote one. I've also tried to proxy the request via Nginx, but I'm totally new to this. As Postman request works, I wonder if there is a way to send the request from my app as if it was a Postman request, but something is not right here and right now I'm totally lost – Jack_Russell Dec 06 '18 at 11:58