0

I have a simple piece of code.

let body = new FormData();
body.set("a", true);
body.set("username", this.user);
body.set("password", this.password);

let headers = new HttpHeaders();
headers.set("Content-Type", 'application/x-www-form-urlencoded')

console.log("about to post");
this.http.post("/endpoint", body, {headers: headers}).subscribe(
    (result) => { console.log("success", result); /*extra code*/},
    (error) => { console.log("error", error); /*extra code*/ },
    () => { console.log("Complete"); /*extra code*/ });

This is a pretty simple subscription.

So i do a post request, and it throws a 401 error network request. The issue I have noticed is that the console will say

about to post
POST [url] 401 (Unauthorized)
Complete

It doesnt carry out the error functionality.

in the constructor http is defined as: private http: HttpClient

So i am a bit torn in understanding as to why it fails to throw the error. Is there something which is failing to work? I was looking at similar posts, such as Catching errors in Angular HttpClient which I thought i was following in regards to a subscription.

On a successful request, it calls success just fine.

Edit I was looking at the code more, and figured that maybe the data or the headers were wrong. So i am going to update them above. It seemed that the data being passed up looked off, so i updated it to be form data. I walked through the endpoint until it hits a throw new Exception("Authorization Error"), but it never calls the error function. Maybe there is something i am missing in the definition of the post request? Maybe something breaks internally because I failed to set something correctly?

Fallenreaper
  • 10,222
  • 12
  • 66
  • 129

1 Answers1

2

Here I have prepared a mock so you can play

Basically it mocks a server call intercepting some http requests with 'FakeBackendInterceptor' component. There I simulate an unauthorized response if you post a request to '/protected' endpoint.

The only component to start the application is HelloComponent which calls the get and post service to mimic both authorized and unauthorized calls.

In the end you were right because it is capturing as an error. Fork it so you can try anything else. I am used to intercept all errors (or unauthorized calls) in one place, I've just added an ErrorInterceptor component so you can try both approaches.

Pay attention to the declaration at app.module (order matters):

providers:    [ 
    { provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true },
    { provide: HTTP_INTERCEPTORS, useClass: FakeBackendInterceptor, multi: true },
  ], 

don't forget to add HttpClientModule to imports:

imports:      [ HttpClientModule, BrowserModule, FormsModule ],

If you don't want to use the interceptor:

  this.service.post().subscribe(
    (result) => { console.log("success", result); /*extra code*/},
    (error) => { 
      console.log("error", error); /*extra code*/ 
      if (error.status === 401)  {
        console.log("You are not authorized");
      }
    },
    () => { console.log("Complete"); /*extra code*/ })
}

I've added yet another extra case so you can deal with 401 in the service itself. If you send a PUT request you can test it:

  let body = new FormData();
  body.set("a", 'true');
  body.set("username", 'user');
  body.set("password", 'password');

  let headers = this.createHeaders();
  
  console.log("calling services unauthorized PUT");
  return this.http.put<any>("/protected", body, { headers, observe: "response" }).
  pipe(
    map(res => {
    if (res.status === 400 || res.status === 401) {
      throw new Error(res.body.message);
    }
    return res.body;
  }));
dreamcrash
  • 47,137
  • 25
  • 94
  • 117
Tena
  • 600
  • 4
  • 14
  • is there a difference between HttpHeaders and Headers? If 401 is not an error but a status, should it then have fired success ? I would have thought it binary.... either it carries out the success function, or not. So that being said, I would think the result would print out "success" at least. No? – Fallenreaper Mar 12 '19 at 17:36
  • sorry, it's HttpHeaders and from angular/common/ in new versions. I point you to the documentation so you can understand better the inner workings of HTTP responses. What I do is to add a component to deal with all the unauthorized responses instead of doing it one by one. I edit my answer. – Tena Mar 12 '19 at 17:44
  • It sounds like response is the success function. Given that, and the fact i have stated it does not fire success function when error is called, I would like to see a functional demo stating this use case. As far as i can tell, this is not a valid answer. – Fallenreaper Mar 12 '19 at 17:50
  • let me mock an stackblitz for you – Tena Mar 12 '19 at 17:59
  • You were right. The issue was an interceptor which was tucked away in our codebase ineeded to look at – Fallenreaper Mar 12 '19 at 19:36
  • great! problem solved then \o/, glad to know, because it was starting to making me crazy :) BTW I fixed some minor changes with headers and the request itself. – Tena Mar 12 '19 at 19:38
  • makes sense. Yeah it took me awhile but when you implemented the interceptor, that is where i started to look deeper into the codebase to see what may have been set up in regards to that. You have been a solid help. – Fallenreaper Mar 12 '19 at 20:40