Fetch Client

Aurelia's @aurelia/fetch-client is a powerful HTTP client built on the native Fetch API, designed specifically for modern web applications. It provides a clean, promise-based interface for making HTTP requests with enterprise-grade features like intelligent caching, automatic retries, and flexible interceptors.

import { IHttpClient } from '@aurelia/fetch-client';
import { resolve } from '@aurelia/kernel';

class ApiService {
  private http = resolve(IHttpClient);
  
  async getUsers() {
    const response = await this.http.get('/api/users');
    return response.json();
  }
}

Why Use Aurelia's Fetch Client?

While the native Fetch API is powerful, Aurelia's wrapper adds essential features for real-world applications:

Built for Production

  • Automatic retries with exponential backoff

  • Intelligent caching with background refresh

  • Request/response interceptors for cross-cutting concerns

  • Centralized configuration for consistency across your app

Developer Experience

  • Fluent API with method chaining

  • TypeScript-first with full type safety

  • Dependency injection integration

  • Built-in error handling patterns

Performance Features

  • Request deduplication through caching

  • Background data refresh for stale content

  • Request tracking and status monitoring

  • Minimal overhead over native fetch

Quick Start

import { IHttpClient, json } from '@aurelia/fetch-client';
import { resolve } from '@aurelia/kernel';

class UserService {
  private http = resolve(IHttpClient);
  
  constructor() {
    // One-time configuration
    this.http.configure(config => config
      .withBaseUrl('https://api.example.com/')
      .withDefaults({
        headers: { 'X-API-Key': 'your-key' }
      })
      .rejectErrorResponses() // Reject on 4xx/5xx status codes
    );
  }
  
  async createUser(userData) {
    return this.http.post('/users', {
      body: json(userData)
    });
  }
  
  async getUser(id) {
    const response = await this.http.get(`/users/${id}`);
    return response.json();
  }
}

Core Features

HTTP Methods

Full support for all HTTP verbs with consistent interfaces:

http.get(url, options?)
http.post(url, options?)
http.put(url, options?)
http.patch(url, options?)
http.delete(url, options?)
http.fetch(url, options?) // For custom methods

Request Status Tracking

Monitor your application's network activity:

console.log(http.isRequesting);        // boolean
console.log(http.activeRequestCount);  // number of active requests
console.log(http.isConfigured);        // configuration status

Smart Base URL Handling

http.configure(config => config.withBaseUrl('https://api.example.com/v1/'));

// Relative URLs use the base
await http.get('/users');     // → https://api.example.com/v1/users

// Absolute URLs are unchanged  
await http.get('https://other-api.com/data'); // → https://other-api.com/data

Advanced Capabilities

Intelligent Caching

Reduce server load and improve performance with built-in caching:

import { CacheInterceptor } from '@aurelia/fetch-client';

const cacheInterceptor = container.invoke(CacheInterceptor, [{
  cacheTime: 300_000,     // Cache for 5 minutes
  refreshInterval: 60_000  // Background refresh every minute
}]);

http.configure(config => config.withInterceptor(cacheInterceptor));

Automatic Retries

Handle network failures gracefully:

import { RetryStrategy } from '@aurelia/fetch-client';

http.configure(config => config.withRetry({
  maxRetries: 3,
  strategy: RetryStrategy.exponential,
  doRetry: (response) => response.status >= 500 // Only retry server errors
}));

Powerful Interceptors

Implement cross-cutting concerns like authentication, logging, and error handling:

http.configure(config => config.withInterceptor({
  request(request) {
    // Add auth header to every request
    request.headers.set('Authorization', `Bearer ${getToken()}`);
    return request;
  },
  
  response(response) {
    // Log all responses
    console.log(`${response.status} ${response.url}`);
    return response;
  },
  
  responseError(error, request) {
    if (error.status === 401) {
      // Handle token expiration
      return refreshToken().then(() => http.fetch(request));
    }
    throw error;
  }
}));

What's Different from Native Fetch?

Feature
Native Fetch
Aurelia Fetch Client

Error Handling

Only network errors reject

Can reject on HTTP error status

Configuration

Per-request

Centralized with defaults

Caching

Manual implementation

Built-in with multiple strategies

Retries

Manual implementation

Automatic with multiple strategies

Interceptors

None

Request/Response/Error interceptors

JSON Handling

Manual stringify/parse

Helper functions and auto-detection

Base URLs

Manual concatenation

Smart URL resolution

Request Tracking

Manual

Built-in status monitoring

Common Use Cases

API Client Setup:

// Configure once, use everywhere
http.configure(config => config
  .withBaseUrl('https://api.example.com/v1/')
  .withDefaults({
    headers: {
      'Content-Type': 'application/json',
      'Authorization': () => `Bearer ${getCurrentToken()}`
    }
  })
  .rejectErrorResponses()
  .withRetry({ maxRetries: 3 })
);

Authentication Integration:

http.configure(config => config.withInterceptor({
  responseError(error, request, client) {
    if (error.status === 401) {
      return refreshAuthToken()
        .then(() => client.fetch(request));
    }
    throw error;
  }
}));

Form Submissions:

const formData = new FormData();
formData.append('file', fileInput.files[0]);
formData.append('description', 'Profile photo');

await http.post('/upload', { body: formData });

Integration with Aurelia DI

The fetch client is designed to work seamlessly with Aurelia's dependency injection system:

import { IHttpClient } from '@aurelia/fetch-client';
import { resolve } from '@aurelia/kernel';

export class ApiService {
  private http = resolve(IHttpClient);
  
  async getData() {
    return this.http.get('/api/data');
  }
}

Each service gets its own configured instance when using resolve(IHttpClient), allowing for service-specific configurations while maintaining the global defaults.

Next Steps

The Aurelia Fetch Client transforms the native Fetch API from a low-level primitive into a production-ready HTTP client that scales with your application's needs.

Last updated

Was this helpful?