Keywords: Angular | HTTP Call | Response Type
Abstract: This article provides an in-depth exploration of how to correctly set the response type to text when making HTTP calls in Angular 6, addressing the common error 'Backend returned code 200, body was: [object Object]'. It analyzes the root causes, offers step-by-step solutions including the use of the responseType option, handles TypeScript type errors, and compares different approaches. Through code examples and detailed explanations, it helps developers understand the internal mechanisms of Angular's HTTP client for seamless integration with REST APIs returning plain text.
Problem Background and Error Analysis
In Angular applications, when making HTTP POST calls to a Spring REST API that returns plain strings (e.g., "success" or "fail"), developers often encounter the error: Backend returned code 200, body was: [object Object]. This error indicates that although the backend successfully returns an HTTP status code of 200, the Angular client incorrectly parses the response body as an object instead of the expected string. The root cause lies in Angular's HTTP client defaulting to a JSON response type, which leads to misprocessing of non-JSON responses.
Solution: Setting responseType to 'text'
To resolve this issue, the key is to explicitly specify responseType: 'text' in the HTTP request options. This instructs Angular to treat the response body as plain text rather than attempting to parse it as JSON. Below is a corrected code example based on the original addToCart method:
addToCart(productId: number, quantity: number): Observable<any> {
const headers = new HttpHeaders().set('Content-Type', 'application/json; charset=utf-8');
return this.http.post(
'http://localhost:8080/order/addtocart',
{ dealerId: 13, createdBy: "-1", productId, quantity },
{ headers, responseType: 'text' }
).pipe(catchError(this.errorHandlerService.handleError));
}In this corrected version:
- Remove Generic Type Parameter: The original code used
this.http.post<any>(...), but whenresponseTypeis set to 'text', Angular's HTTP client method signature does not include a generic parameter because it always returnsObservable<string>. Retaining the generic parameter can cause TypeScript compilation errors, such as "Type 'text' is not assignable to type 'json'". - Correct Request Headers: Since the request body is a JavaScript object (e.g.,
{ dealerId: 13, ... }), it should be serialized as JSON. Therefore, setting theContent-Typeheader toapplication/json; charset=utf-8is more appropriate, ensuring the backend can correctly parse the request data. The originaltext/plainheader might cause mismatches, as objects are not plain text. - Use responseType: 'text': This option forces the HTTP client to return the response body as a string, thereby avoiding the
[object Object]error. Now, when the API returns "success" or "fail", the response will be correctly captured as a string value.
In-Depth Understanding of Angular HTTP Client Response Types
Angular's HttpClient offers multiple response type options, including 'json' (default), 'text', 'blob', and 'arraybuffer'. Understanding these differences is crucial for handling various API responses:
- responseType: 'json': The default value. Angular attempts to parse the response body as a JSON object. If the response is not valid JSON (e.g., plain text), it throws an error or returns unexpected values.
- responseType: 'text': Returns the response body as a raw string without any parsing. This is suitable for APIs returning plain text, HTML, or custom formats.
- Other Types: Such as 'blob' for binary data (e.g., images) and 'arraybuffer' for raw byte data.
At the method signature level, Angular defines overloads for different responseType values:
// When responseType is 'json' (default), the method accepts a generic parameter
post<T>(url: string, body: any | null, options?: {
headers?: HttpHeaders | { [header: string]: string | string[] };
responseType?: 'json';
// Other options...
}): Observable<T>;
// When responseType is 'text', the method returns Observable<string> with no generic parameter
post(url: string, body: any | null, options: {
headers?: HttpHeaders | { [header: string]: string | string[] };
responseType: 'text';
// Other options...
}): Observable<string>;This is why, when setting responseType: 'text', the generic parameter (e.g., <any>) must be removed to avoid TypeScript type mismatch errors.
Error Handling and Best Practices
After correcting the code, the error handling service (e.g., ErrorHandlerService) should be able to capture HTTP errors normally. For instance, if the backend returns a 4xx or 5xx status code, the handleError method logs the error and returns a user-friendly message. Ensure that error handling logic adapts to text responses: in text mode, error response bodies are also strings, so error.error will directly contain the text content instead of a parsed object.
Best practices recommendations:
- Always Match Content-Type with Request Body: Use
application/jsonheader for JSON data andtext/plainfor plain text. In the example, since the request body is an object, the JSON header is more appropriate. - Enable Detailed Logging During Development: Use browser developer tools or Angular's debug mode to inspect requests and responses, verifying header and response type settings.
- Test Edge Cases: For example, ensure the client handles scenarios where the API returns empty strings or unexpected text robustly.
Comparison and Supplements with Other Answers
Referring to other community answers, some variant methods are worth discussing:
- Using 'text' as const: In some TypeScript versions, explicit type assertions (e.g.,
responseType: 'text' as const) can help the compiler recognize literal types and avoid potential type errors. However, this is often unnecessary as Angular's type definitions handle this by default. - Avoid Unnecessary Mapping: Some answers suggest using
.map(res => res)after the HTTP call, which is typically redundant sinceObservable<string>already provides the response string directly.
In summary, setting responseType: 'text' is the core solution for handling plain text API responses. By understanding Angular's HTTP client design, developers can avoid common pitfalls and build more reliable applications.