3

I have an angular 4 front end with a CakePHP 3 backend. When I make a request to an API end point using my browser or Rest Client I receive a response. But when I send the response from the angular service it immediately shows cancelled in the network.

At first I assumed it was a CORS issue. I have tried both with and without CORS enabled. I also added $this->Security->csrfCheck = false; to my AppController.php which led me to believe that the local server is never hit (no breakpoints were firing).

So instead I am looking at Angular side of the equation. I have attempted to set my headers but that also does not work.

import { Headers, Http, Response, RequestOptions } from '@angular/http';

login(loginData) {
    const headers = new Headers({'Content-Type': 'application/json'});

    const url:string = this.backendUrl + '/auth/login/?';

    return this.Http.post(
        url,
        JSON.stringify(loginData),
        { headers: headers }
    ).map(
        res => res.json
    ).map(
        response => function(response) {
            ...
        },
        error => function(error) {
            ...
        }
    );
}

I am in the process of migrating from 1 to 4. So I know that it worked in Angular 1 using $http requests.

function login(loginData) {
   var = this.backendUrl + '/auth/login/?';

   $http.post(url, loginData).then( ... );
}

Here is my component which uses the subscription:

login = function(activeUser):ActiveUser|boolean {
    this.isLoggingIn = true;

    return this.LoginService.login(activeUser).subscribe(
        activeUser => function(activeUser) {
            if (activeUser) {
                this.activeUser = activeUser;
            } else {
                this.reset();
            }

            return activeUser;
        }.bind(this)
    ).complete(
        function() {
            this.isLoggingIn = false;
        }.bind(this)
    );
};
Jeremy
  • 3,620
  • 9
  • 43
  • 75
  • angular http observables are cold by default. Meaning that your login function is just setting up the http request. To actually initiate the http request you must subscribe to the observable this.login.subscribe(); – LLai Aug 11 '17 at 01:32
  • Possible duplicate of [Angular 2 http get not getting](https://stackoverflow.com/questions/41381200/angular-2-http-get-not-getting) – AT82 Aug 11 '17 at 08:00
  • This problem is _slightly_ different, the call is being made to the network and getting cancelled. My problem appears to be around the subscribe method not being set up correctly. The other question is completely missing the subscribe method which is causing no call to be made at all. It helped put me on the right track though, thanks! – Jeremy Aug 11 '17 at 14:07

2 Answers2

0

I'm not sure why you are mapping twice.

Just for comparison ... this is what my post looks like (see below). It is posting a save, but the syntax should be the same for a login.

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

        return this.http.post(this.baseUrl, product, options)
            .map(this.extractData)
            .do(data => console.log('createProduct: ' + JSON.stringify(data)))
            .catch(this.handleError);
    }

    private extractData(response: Response) {
        let body = response.json();
        return body.data || {};
    }

    private handleError(error: Response): Observable<any> {
        // in a real world app, we may send the server to some remote logging infrastructure
        // instead of just logging it to the console
        console.error(error);
        return Observable.throw(error.json().error || 'Server error');
    }

How are you calling this service?

My component code looks like this:

        this.productService.saveProduct(this.product)
            .subscribe(
                () => this.onSaveComplete(`${this.product.productName} was saved`),
                (error: any) => this.errorMessage = <any>error
            );

Note that it is the subscribe that kicks off the Observable and executes the post.

DeborahK
  • 57,520
  • 12
  • 104
  • 129
  • When I try that I get `Property 'do' does not exist on type 'Observable'` – Jeremy Aug 11 '17 at 02:45
  • You can either remove it (it is only for use in debugging) or you can import the do operator. `import 'rxjs/add/operator/do';` – DeborahK Aug 11 '17 at 04:26
  • I have included my component which is calling `subscribe`. I have tried removing the second `map` call as well with no luck. – Jeremy Aug 11 '17 at 14:02
  • When I use an empty `subscribe` method it appears to work. – Jeremy Aug 11 '17 at 14:04
0

The problem had to do with how Angular $http now handles CORS requests. In the updated version there are two requests sent, an OPTIONS request and then the actual GET/POST request. So I had to change my backend to return a 200 on the OPTIONS without executing the command and instead execute on the second request.

Jeremy
  • 3,620
  • 9
  • 43
  • 75