o7_salute
o7_salute

Reputation: 73

http.request returning "{ type: 0 }" before actual response

Every time I submit my Login form, the return res; in the Login() method (found below) code gets executed twice.

The first response is a simple object { type: 0 }, the second is the actual response I'm looking for.

Why would return res; get called twice? How to I prevent that from happening?

I've stepped through the code and confirm that login() is only being called once, my HttpInterceptor is only being called once and the remote request is only being sent once.

I've upload this image to help explain what's happening. You can see that only 1 remote request has been executed, but 2 responses have been logged to the console.

This problem only started a few hours ago. I've been struggling with getting ionic serve to work with CORS, I tried using proxy.conf.json and proxy.js but without having access to the API I can't allow access. For development purposes I've disable CORS in Chrome using this extension because once I run the app on a mobile device it won't require CORS.

Additional toubleshooting I've tried:

  1. Disabled the Allow-Control-Allow-Origin: * extension in Chrome and the issue persists
  2. I removed the HttpInterceptor from the app.module.ts and the issue persists
  3. I've tried different remote URLs (even localhost) and the issue persists
  4. Shutdown Chrome and restarted PC and the issue persists
  5. Tried using FireFox and the issue persists
  6. I created a new Ionic4 Project and copy / pasted the same code and the issue persists
  7. I tried in Chrome on a seperate machine and the issue persists

Here is my login() observable that is subscribed to in my onSubmit() method:

login(username: string, password: string) {

  const body = new FormData();

  body.append('username', username);
  body.append('password', password);

  const request = new HttpRequest('POST', '[URL]', body);

  return this.http.request(request)
  .pipe(map(res => {

    return res;

  }));

}

Here is my onSubmit() and HttpInterceptor if it helps.

onSubmit () {

  this.isSubmitted = true; // I've put a break point here to make sure this method is called once

  if (!this.login.valid) {

    return;

  }

  this.authenticationService.login(this.login.value.username, this.login.value.password).subscribe((res: any) => {

  console.log(res); // this is the log that is displayed in the above screen shot

  });

}
export class AuthInterceptor implements HttpInterceptor {

  constructor() { }

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    // Check auth here...

    return next.handle(request);

  }

}

I expect return res; to be called only once.

Upvotes: 6

Views: 8034

Answers (4)

vlz
vlz

Reputation: 1039

Short answer: Don't use http.request(), use http.post() or similar.

Long answer:

You are using HttpClient.request() with an HttpRequest object and the docs on request() state that in this case you get an Observable over the stream of all HttpEvents. The object

{ type: 0 }

is simply the first HttpEvent of type Sent, emitted directly after the request is sent but before the response arrives. The response then is the next event after that. (see HttpEventType for all possible events) To get just the response, you can simply use another method (or modify your call of request() according to the docs)

Upvotes: 3

Mehrnoosh
Mehrnoosh

Reputation: 111

I could not see any problem within the code you have mentioned but with what you have described, It seems you have set some options for your http request and the response is observing events instead of response.

options: {
    headers?: HttpHeaders | {[header: string]: string | string[]},
    observe?: 'body' | 'events' | 'response',
    params?: HttpParams|{[param: string]: string | string[]},
    reportProgress?: boolean,
    responseType?: 'arraybuffer'|'blob'|'json'|'text',
    withCredentials?: boolean,
  }

The observe option specifies how much of the response to return. This link might be helpful

Upvotes: 1

Muhammad Sohaib
Muhammad Sohaib

Reputation: 11

Please use the single return statement instead of returning 2 times Try Using The Below Code , thanks

login(username: string, password: string) {

  const body = new FormData();

  body.append('username', username);
  body.append('password', password);

  const request = new HttpRequest('POST', '[URL]', body);

  this.http.request(request)
  .pipe(map(res => {

    return res;

  }));

}

Upvotes: 0

o7_salute
o7_salute

Reputation: 73

It turns out I needed to change

login(username: string, password: string) {

  const body = new FormData();

  body.append('username', username);
  body.append('password', password);

  const request = new HttpRequest('POST', '[URL]', body);

  return this.http.request(request)
  .pipe(map(res => {

    return res;

  }));

}

to the following

login(username: string, password: string) {

  const body = new FormData();

  body.append('username', username);
  body.append('password', password);

  return this.http.post<any>(`[URL]`, body)
  .pipe(map(res => {
    return res;
  }));

}

Upvotes: 1

Related Questions