Working with Headers and Query Parameters in Angular HttpClient

Introduction

When building web applications, HTTP requests often require additional data to be sent along with them. This can include headers (for authentication, content type, etc.) and query parameters (for pagination, searching, filtering, or sorting).

Angular’s HttpClient provides powerful options to attach both headers and parameters dynamically. These make your API interactions more flexible, secure, and maintainable.

In this detailed guide, we’ll explore how to use HttpHeaders and HttpParams in Angular to send custom headers and query parameters in GET, POST, PUT, and DELETE requests.

Table of Contents

  1. Setting Up HttpClientModule
  2. Creating a Data Service
  3. What Are HTTP Headers?
  4. Why Use Headers in Angular?
  5. Creating and Adding Headers
  6. Example: Adding Authorization Header
  7. Dynamic Headers
  8. Setting Multiple Headers
  9. Removing and Appending Headers
  10. Using Headers with POST, PUT, and DELETE
  11. What Are Query Parameters?
  12. Creating Query Parameters in Angular
  13. Example: Pagination with Query Parameters
  14. Example: Filtering Data Using Parameters
  15. Dynamic Parameters in Requests
  16. Combining Headers and Params
  17. Example: GET Request with Headers and Params
  18. Using Observables for Request Handling
  19. Handling Errors in Header-Based Requests
  20. Reusing Headers and Params with Services
  21. Using Interceptors for Global Headers
  22. Adding Auth Tokens Automatically
  23. Using Environment Variables for API URLs
  24. Best Practices for Headers and Params
  25. Full Working Example (User Service)
  26. Conclusion

1. Setting Up HttpClientModule

Before using headers and parameters, you must set up the HttpClientModule in your main app module.

import { HttpClientModule } from '@angular/common/http';
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, HttpClientModule],
  bootstrap: [AppComponent]
})
export class AppModule {}

This enables HttpClient for the entire application.


2. Creating a Data Service

A service allows you to centralize your API logic.

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class DataService {
  private apiUrl = 'https://jsonplaceholder.typicode.com/users';
  constructor(private http: HttpClient) {}
}

3. What Are HTTP Headers?

Headers are key-value pairs sent along with an HTTP request or response.
They provide metadata such as authentication information, content type, or caching policies.

For example:

  • Content-Type: Defines the format of the request body (e.g., JSON, XML).
  • Authorization: Used for access tokens or credentials.
  • Accept: Defines the response format expected by the client.

4. Why Use Headers in Angular?

You might need headers for:

  • Sending authentication tokens.
  • Specifying content type.
  • Managing cache control.
  • Controlling API versioning.
const headers = new HttpHeaders({ 'Authorization': 'Bearer token' });

5. Creating and Adding Headers

Headers in Angular are created using the HttpHeaders class.

const headers = new HttpHeaders({
  'Content-Type': 'application/json',
  'Authorization': 'Bearer my-token'
});

this.http.get(this.apiUrl, { headers });

6. Example: Adding Authorization Header

Here’s how to add a token header in a service method.

getUsers(): Observable<any> {
  const headers = new HttpHeaders({
Authorization: 'Bearer 12345abcde'
}); return this.http.get(this.apiUrl, { headers }); }

In the component:

this.dataService.getUsers().subscribe(data => {
  console.log('Users:', data);
});

7. Dynamic Headers

Sometimes, headers need to be generated at runtime (for example, after login).

getProtectedData(token: string): Observable<any> {
  const headers = new HttpHeaders({
Authorization: Bearer ${token}
}); return this.http.get(${this.apiUrl}/protected, { headers }); }

8. Setting Multiple Headers

You can set multiple headers at once.

const headers = new HttpHeaders()
  .set('Content-Type', 'application/json')
  .set('Authorization', 'Bearer 123')
  .set('Custom-Header', 'AppData');
this.http.get(this.apiUrl, { headers }).subscribe();

9. Removing and Appending Headers

The HttpHeaders object is immutable. Each operation like set or append returns a new instance.

let headers = new HttpHeaders().set('Authorization', 'Bearer token');
headers = headers.append('App-Version', '1.0.0');

To remove a header:

headers = headers.delete('Authorization');

10. Using Headers with POST, PUT, and DELETE

Headers can be attached to any type of request.

addUser(user: any): Observable<any> {
  const headers = new HttpHeaders({ 'Content-Type': 'application/json' });
  return this.http.post(this.apiUrl, user, { headers });
}

Similarly for PUT:

updateUser(id: number, user: any): Observable<any> {
  const headers = new HttpHeaders({ 'Authorization': 'Bearer xyz' });
  return this.http.put(${this.apiUrl}/${id}, user, { headers });
}

And DELETE:

deleteUser(id: number): Observable<any> {
  const headers = new HttpHeaders({ 'Authorization': 'Bearer xyz' });
  return this.http.delete(${this.apiUrl}/${id}, { headers });
}

11. What Are Query Parameters?

Query parameters are appended to the end of a URL to pass extra information to the server.
They are useful for:

  • Filtering results
  • Paginating data
  • Searching
  • Sorting

Example:

https://api.example.com/users?page=2&limit=10

12. Creating Query Parameters in Angular

Angular provides the HttpParams class to build parameters easily.

const params = new HttpParams()
  .set('page', '1')
  .set('limit', '10');

Usage:

this.http.get(this.apiUrl, { params });

13. Example: Pagination with Query Parameters

getUsers(page: number, limit: number): Observable<any> {
  const params = new HttpParams()
.set('page', page)
.set('limit', limit);
return this.http.get(this.apiUrl, { params }); }

Component:

this.dataService.getUsers(1, 10).subscribe(data => {
  console.log('Page 1 Users:', data);
});

14. Example: Filtering Data Using Parameters

Query parameters can also filter results dynamically.

searchUsers(name: string): Observable<any> {
  const params = new HttpParams().set('name', name);
  return this.http.get(this.apiUrl, { params });
}
this.dataService.searchUsers('John').subscribe(result => {
  console.log(result);
});

15. Dynamic Parameters in Requests

Parameters can be added conditionally based on user actions.

getFilteredUsers(filters: any): Observable<any> {
  let params = new HttpParams();
  if (filters.name) params = params.set('name', filters.name);
  if (filters.age) params = params.set('age', filters.age);
  if (filters.status) params = params.set('status', filters.status);
  return this.http.get(this.apiUrl, { params });
}

16. Combining Headers and Params

You can send both headers and parameters together in a single request.

const headers = new HttpHeaders({ 'Authorization': 'Bearer token' });
const params = new HttpParams().set('page', '2').set('limit', '5');

this.http.get(this.apiUrl, { headers, params }).subscribe();

17. Example: GET Request with Headers and Params

getUsersWithAuthAndPagination(token: string, page: number): Observable<any> {
  const headers = new HttpHeaders({ Authorization: Bearer ${token} });
  const params = new HttpParams().set('page', page.toString());
  return this.http.get(this.apiUrl, { headers, params });
}

18. Using Observables for Request Handling

Angular’s HttpClient returns Observables, making it easy to handle asynchronous data and responses.

this.dataService.getUsersWithAuthAndPagination('token', 2)
  .subscribe(response => {
console.log('Received data:', response);
});

You can also use RxJS operators like map, catchError, or tap for transformation and error handling.


19. Handling Errors in Header-Based Requests

You can use catchError to handle failed API requests.

import { catchError } from 'rxjs/operators';
import { throwError } from 'rxjs';

getSecureData(): Observable<any> {
  const headers = new HttpHeaders({ Authorization: 'Bearer invalid-token' });
  return this.http.get(this.apiUrl, { headers }).pipe(
catchError(error =&gt; {
  console.error('API Error:', error);
  return throwError(() =&gt; error);
})
); }

20. Reusing Headers and Params with Services

You can define reusable header and parameter logic inside your service.

private createAuthHeaders(token: string): HttpHeaders {
  return new HttpHeaders({ Authorization: Bearer ${token} });
}

private createPaginationParams(page: number, limit: number): HttpParams {
  return new HttpParams().set('page', page).set('limit', limit);
}

getPaginatedData(token: string, page: number, limit: number): Observable<any> {
  const headers = this.createAuthHeaders(token);
  const params = this.createPaginationParams(page, limit);
  return this.http.get(this.apiUrl, { headers, params });
}

21. Using Interceptors for Global Headers

Interceptors allow adding headers automatically to all HTTP requests without repeating code.

import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const cloned = req.clone({
  setHeaders: {
    Authorization: 'Bearer my-global-token'
  }
});
return next.handle(cloned);
} }

Register the interceptor in your app module:

import { HTTP_INTERCEPTORS } from '@angular/common/http';

@NgModule({
  providers: [
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }
] }) export class AppModule {}

22. Adding Auth Tokens Automatically

Once the interceptor is in place, every request sent by HttpClient will automatically include the token header.

This eliminates the need to manually add headers in every service method.


23. Using Environment Variables for API URLs

Instead of hardcoding API URLs, define them in your environment.ts files.

export const environment = {
  production: false,
  apiUrl: 'https://api.example.com'
};

Usage in service:

import { environment } from '../environments/environment';

private apiUrl = ${environment.apiUrl}/users;

24. Best Practices for Headers and Params

  1. Use Services for All API Calls
    Keep components clean and focused on UI logic.
  2. Centralize Headers
    Use interceptors or helper functions to avoid duplication.
  3. Use Strong Typing
    Create TypeScript interfaces for responses.
  4. Avoid Hardcoding Tokens
    Store tokens securely using local storage or Angular services.
  5. Handle Errors Gracefully
    Use catchError and provide user feedback.
  6. Combine Headers and Params Efficiently
    Don’t create new HttpHeaders or HttpParams unnecessarily.
  7. Leverage RxJS Operators
    Use map, tap, finalize, and catchError for robust data streams.
  8. Use Environment Configurations
    Keep different API URLs for development and production.

25. Full Working Example (User Service)

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';
import { environment } from '../environments/environment';

@Injectable({
  providedIn: 'root'
})
export class UserService {
  private apiUrl = ${environment.apiUrl}/users;

  constructor(private http: HttpClient) {}

  getUsers(token: string, page: number, limit: number): Observable<any> {
const headers = new HttpHeaders({ Authorization: Bearer ${token} });
const params = new HttpParams().set('page', page).set('limit', limit);
return this.http.get(this.apiUrl, { headers, params });
} addUser(token: string, user: any): Observable<any> {
const headers = new HttpHeaders({
  Authorization: Bearer ${token},
  'Content-Type': 'application/json'
});
return this.http.post(this.apiUrl, user, { headers });
} updateUser(token: string, id: number, user: any): Observable<any> {
const headers = new HttpHeaders({ Authorization: Bearer ${token} });
return this.http.put(${this.apiUrl}/${id}, user, { headers });
} deleteUser(token: string, id: number): Observable<any> {
const headers = new HttpHeaders({ Authorization: Bearer ${token} });
return this.http.delete(${this.apiUrl}/${id}, { headers });
} }

Usage in component:

this.userService.getUsers('myToken', 1, 10).subscribe(users => {
  console.log(users);
});

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *