7

I'm trying to do a http.post but chrome is showing the following error:

No Access-Control-Allow-Origin.

My Angular function is:

onSubmit(event: Event) {
  event.preventDefault();
    this.leerDatos()
    .subscribe(res => {
      //datos = res.json();
      console.log("Data send");
    }, error => {
          console.log(error.json());
      });



  }

  leerDatos(): Observable<any> {
    let headers = new Headers({ 'Content-Type': 'application/json' });
    let options = new RequestOptions({ headers: headers });

    return this.http.post(`http://localhost:8080/LegoRepositoryVincle/CoreServlet`, { name: "bob" }, options)
                    //.map(this.extractData)
                    //.catch(this.handleError);
  }

And my servlet doPost method includes:

response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
response.addHeader("Access-Control-Allow-Origin","http://localhost:4200");
response.addHeader("Access-Control-Allow-Credentials", "true");
response.addHeader("Access-Control-Allow-Methods","GET,POST");
response.addHeader("Access-Control-Allow-Headers","X-PINGOTHER, Origin, X-Requested-With, Content-Type, Accept, Cache-Control, Pragma");
5
  • 2
    That’s likely because your servlet answers POST requests only - but not the pre-flight OPTIONS request that will occur in this situation. developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS Commented Jul 5, 2017 at 12:01
  • So what i should do? Commented Jul 5, 2017 at 21:30
  • Make it handle such pre-flight requests properly, too. Commented Jul 6, 2017 at 7:38
  • Finally I moved my angular project into my webcontent and working in the same host works correctly Commented Jul 7, 2017 at 11:34
  • I found this solution to avoid CORS between ports thejavageek.com/2017/06/14/… Commented Jul 19, 2017 at 21:32

2 Answers 2

14

If you still want to use CORS while developing you can solve this kind of issue using angular/cli --proxy-config.

Essentially, if you want to make requests to a remote machine having, for example, nginx web server running, you perform all your calls to your very same application, e.g. localhost:4200 (default in angular/cli). Then you redirect those responses to your server using --proxy-config.

Let's suppose your server's api have all the /api prefix entrypoint. You need to create a file called proxy.config.json in the root of your project and configure it like:

{
    "/api" : {
        "target" : "http://xx.xxx.xxx.xx", // Your remote address
        "secure" : false,
        "logLevel" : "debug", // Making Debug Logs in console
        "changeOrigin": true
    }
}

And then, all your http requests will point to localhost:4200/api/.

Finally, you should be done by running ng server --proxy-config proxy.config.json.

If you notice that some headers are missing in the request, add them from your web server or edit your http.service.ts to append those like in this example:

import { Injectable } from '@angular/core';
import { Http, Headers, RequestOptions } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import { isNull } from 'lodash';

@Injectable()
export class HttpClientService {

  private _host: string;
  private _authToken: string;
  private _options: RequestOptions = null;

  constructor(private _http: Http, private _config: AppConfig, private _localStorageService: LocalStorageService) {
      this._host = ''; // Your Host here, get it from a configuration file
      this._authToken = ''; // Your token here, get it from API
  }

  /**
   * @returns {RequestOptions}
   */
   createAuthorizationHeader(): RequestOptions {
      // Just checking is this._options is null using lodash
      if (isNull(this._options)) {
        const headers = new Headers();
        headers.append('Content-Type', 'application/json; charset=utf-8');
        headers.append('Authorization', this._authToken);
        this._options = new RequestOptions({headers: headers});
      }
      return this._options;
   }

   /**
    * @param url {string}
    * @param data {Object}
    * @return {Observable<any>}
    */
    get(url?: string, data?: Object): Observable<any> {
      const options = this.createAuthorizationHeader();
      return this._http.get(this._host + url, options);
    }

   /**
    * @param url {string}
    * @param data {Object}
    * @return {Observable<any>}
    */
    post(url?: string, data?: Object): Observable<any> {
      const body = JSON.stringify(data);
      const options = this.createAuthorizationHeader();
      return this._http.post(this._host + url, body, options);
    }

}

So, you would perform all of your api calls through this service like

import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { HttpClientService } from './http.service.ts';

export class TestComponent implements OnInit {

  _observable: Observable<any> = null;

  constructor(private _http: HttpClientService) { }

  ngOnInit() {
      this._observable = this _http.get('test/')
                .map((response: Response) => console.log(response.json()));
  }

}

Angular 5 Update:

In app.module.ts now you need to replace import { HttpModule } from '@angular/http'; with import { HttpClientModule } from '@angular/common/http';.

The service changes a bit to:

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { isNull, isUndefined } from 'lodash';

@Injectable()
export class HttpClientService {

  private _host: string;
  private _authToken: string;
  private __headers: HttpHeaders;

  constructor(private _http: HttpClient, private _config: AppConfig, private _localStorageService: LocalStorageService) {
      this._host = ''; // Your Host here, get it from a configuration file
      this._authToken = ''; // Your token here, get it from API
  }

  /**
   * @returns {HttpHeaders}
   */
   createAuthorizationHeader(): HttpHeaders {
      // Just checking is this._options is null using lodash
      if (isNull(this.__headers)) {
        const headers = new HttpHeaders()
           .set('Content-Type', 'application/json; charset=utf-8')
           .set('Authorization', this. _authToken || '');
        this.__headers= new RequestOptions({headers: headers});
      }

      return this.__headers;
   }

   /**
    * @param url {string}
    * @param data {Object}
    * @return {Observable<any>}
    */
    get(url?: string, data?: Object): Observable<any> {
      const options = this.createAuthorizationHeader();
      return this._http.get(this._host + url, {
          headers : this.createAuthorizationHeader()
      });
    }

   /**
    * @param url {string}
    * @param data {Object}
    * @return {Observable<any>}
    */
    post(url?: string, data?: Object): Observable<any> {
      const body = JSON.stringify(data);
      const options = this.createAuthorizationHeader();
      return this._http.post(this._host + url, body, {
          headers : this.createAuthorizationHeader()
      });
    }
}
Sign up to request clarification or add additional context in comments.

Comments

1

You may use Angular CLI proxy tooling for this purpose.

  • 1. you create a file proxy.config.json at the root of your project
  • 2. you map your API URLs to target URLs using this syntax
 "/api/xxxxxxx" : {
        "target" : "http://www.api.com/xxxxxxx", 
        "secure" : false,
        "logLevel" : "debug",
        "changeOrigin": true
    }
  • 3. Serve your application using
ng serve --proxy-config proxy.config.json

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.