Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTTPClient POST tries to parse a non-JSON response

I'm trying to make a request in Angular and I know that the HTTP response will not be in JSON but in text. However, Angular seems to be expecting a JSON response since the error is the following:

SyntaxError: Unexpected token < in JSON at position 0 at JSON.parse () at XMLHttpRequest.c

As well as

Http failure during parsing for http://localhost:9...

This is the post method:

return this.http.post(this.loginUrl, this.createLoginFormData(username, password), this.httpOptions)
  .pipe(
    tap( // Log the result or error
      data => console.log(data);
      error => console.log(error)
    )
  );

and the headers.

private httpOptions = {

  headers: new HttpHeaders({
    'Accept': 'text/html, application/xhtml+xml, */*',
    'Content-Type': 'application/x-www-form-urlencoded',
    responseType: 'text'
  },

) };

I thought that responseType: 'text' would be enough to make Angular expect a non JSON response.

like image 848
Amy Avatar asked Jun 12 '18 22:06

Amy


4 Answers

You've put responseType: 'text' in the wrong section of your httpOptions - It should sit outside of headers, like so:

private httpOptions = {
  headers: new HttpHeaders({
    'Accept': 'text/html, application/xhtml+xml, */*',
    'Content-Type': 'application/x-www-form-urlencoded'
  }),
  responseType: 'text'
};

With what you had before, a request header of responseType was being sent to the server, rather than simply having an instruction to Angular to actually treat the response as text.

like image 180
Kirk Larkin Avatar answered Oct 17 '22 13:10

Kirk Larkin


This code finally worked for me to xhr download a pdf file (Angular 6 / Laravel 5.6). The specialty for downloading a PDF file vs a text file was 'responseType': 'blob' as 'json'

showPdf(filename: String){
  this.restService.downloadFile(
     'protected/getpdf',
     {'filename': filename}
  )
}

//method from restService
public downloadFile(endpoint:String, postData:Object){

  var restService = this

  var HTTPOptions = {
     headers: new HttpHeaders({
        'Accept':'application/pdf'
     }),
     'responseType': 'blob' as 'json'
  }

  this.http.post(this.baseurl+endpoint,postData,HTTPOptions )
  .subscribe(
     res => {
        console.log(res) //do something with the blob
     },
     error => {
        console.error('download error:', error)
     }, 
     () => {
        console.log('Completed file download.')
     }
  )
}

I found the Solution through Kirk Larkins Answer (thank you a lot!) and a long angular github issue thread https://github.com/angular/angular/issues/18586#issuecomment-323216764

like image 21
Martin Eckleben Avatar answered Oct 17 '22 11:10

Martin Eckleben


If you just want to receive a plain text. You can set Http option without a header.

this.http.get("http://localhost:3000/login",{responseType: 'text'})
.subscribe((result)=>console.log(result))
like image 7
Joe Avatar answered Oct 17 '22 13:10

Joe


By default, Angular sets the response type to JSON.

To override it, you can use headers and set the responseType to 'text' or a simple method would be like this

this.http.get(url, {responseType: 'text'})
like image 4
Lenzman Avatar answered Oct 17 '22 12:10

Lenzman