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 ...

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.

4

7 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.

0

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} )
}

restService.ts:

public downloadFile(endpoint:String, postData:Object){ 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

1

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

this.http.get("",{responseType: 'text'})
.subscribe((result)=>console.log(result))
1

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'})

Using Angular 13:

For text responses:

 var options = { headers: new HttpHeaders({ 'Accept':'text/plain' }), 'responseType': 'text' as 'json' } this.http.post(url,null,options).subscribe(...

For binary file responses:

 var options = { headers: new HttpHeaders({ 'Accept':'image/jpeg' //or 'Accept':'application/pdf' .. etc }), 'responseType': 'blob' as 'json' } this.http.post<Blob>(url,null,options).subscribe(...

Below given is the call from component which downloads the blob, compatible with IE and chrome:

 this.subscribe(this.reportService.downloadReport(this.reportRequest, this.password), response => { let blob = new Blob([response], { type: 'application/zip' }); let fileUrl = window.URL.createObjectURL(blob); if (window.navigator.msSaveOrOpenBlob) { window.navigator.msSaveOrOpenBlob(blob, fileUrl.split(':')[1] + '.zip'); } else { this.reportDownloadName = fileUrl; window.open(fileUrl); } this.spinner = false; this.changeDetectorRef.markForCheck(); }, error => { this.spinner = false; });

Below given is the service method which specifies the response type to be 'blob'

downloadReport(reportRequest: ReportRequest, password: string): Observable<any> { let servicePath = `${basePath}/request/password/${password}`; this.httpOptions.responseType = 'blob'; return this.endpointService.post(endpoint, servicePath, reportRequest, this.httpOptions);
}

Below is the code that makes httpClient call:

 //Make the service call: let obs = this.httpClient.request(method, url, options); //Return the observable: return obs;

I had the same problem after an angular update due http client was updated to parse the response as JSON, failing when the response doesn't contains a valid json (i.e a text or a raw html).

To avoid automatic json parsing, add the header "responseType" as a parameter in the get or post call:

this.http.get(template,{responseType:'text'}) .subscribe(result => { // result contains the "treated as text content" }); 

In general:If expect a Json result (like in a rest api):

 HttpClient.get(url) // returns Observable Json formatted

If text or raw html is expected:

HttpClient.get(url, {responseType:'text'}) // returns a string Observable 

If the return type is unexpected (You'll get the headers as well so you can parse your data properly):

HttpClient.get(url, {observe:response}) //returns Observable<HttpResponse <T>> 

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

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

You Might Also Like