http_nexus 1.0.0 copy "http_nexus: ^1.0.0" to clipboard
http_nexus: ^1.0.0 copied to clipboard

A lightweight but powerful HTTP client wrapper that simplifies API handling with automatic retries, error management, and network failure handling.

HTTP Nexus #

pub package License: MIT

A lightweight HTTP client wrapper for Flutter that handles the tedious parts of API communication. It automatically retries failed requests, manages errors gracefully, and helps you write cleaner networking code.

Why HTTP Nexus? #

Working with APIs in Flutter often means writing the same boilerplate code repeatedly: retry logic, timeout handling, error parsing, and logging. This package takes care of all that so you can focus on building features.

Features #

Core functionality:

  • Automatic retry with exponential backoff
  • Clean error types for different failure scenarios
  • Request and response interceptors
  • Timeout management
  • Request cancellation
  • Automatic JSON encoding and decoding

Advanced capabilities:

  • Offline request queue (stores requests when offline, replays when connected)
  • Built-in logging for debugging
  • Rate limiting to prevent API abuse
  • Global configuration with sensible defaults
  • Authentication token management

Installation #

Add this to your package's pubspec.yaml file:

dependencies:
  http_nexus: ^1.0.0

Then run:

flutter pub get

Quick Start #

import 'package:http_nexus/http_nexus.dart';

// Create a client
final client = SmartApiClient(
  config: ApiClientConfig(
    baseUrl: 'https://api.example.com',
  ),
);

// Make a GET request
final users = await client.get('/users');

// Make a POST request
final newUser = await client.post(
  '/users',
  body: {
    'name': 'John Doe',
    'email': 'john@example.com',
  },
);

Basic Usage #

Configuration #

final config = ApiClientConfig(
  baseUrl: 'https://api.example.com',
  defaultTimeout: Duration(seconds: 30),
  defaultHeaders: {
    'Accept': 'application/json',
  },
  retryPolicy: RetryPolicy(
    maxRetries: 3,
    initialDelay: Duration(seconds: 1),
    backoffMultiplier: 2.0,
  ),
  enableLogging: true,
);

final client = SmartApiClient(config: config);

Making Requests #

GET Request

try {
  final response = await client.get('/posts/1');
  print('Title: ${response['title']}');
} on ServerException catch (e) {
  print('Server error: ${e.statusCode}');
} on NetworkException catch (e) {
  print('Network error: ${e.message}');
}

POST Request

final newPost = await client.post(
  '/posts',
  body: {
    'title': 'My Post',
    'body': 'Post content',
    'userId': 1,
  },
);

PUT Request

final updated = await client.put(
  '/posts/1',
  body: {
    'title': 'Updated Title',
  },
);

DELETE Request

await client.delete('/posts/1');

Query Parameters #

final results = await client.get(
  '/search',
  queryParameters: {
    'q': 'flutter',
    'limit': 10,
  },
);

Custom Headers #

final response = await client.get(
  '/protected',
  headers: {
    'Authorization': 'Bearer token123',
  },
);

Request Cancellation #

// Start request with a cancel token
final cancelToken = 'my-request-1';
final future = client.get('/slow-endpoint', cancelToken: cancelToken);

// Cancel the request
client.cancelRequest(cancelToken);

Using Interceptors #

Logging Interceptor

final client = SmartApiClient(config: config);
client.addRequestInterceptor(LoggingInterceptor());

Authentication Interceptor

final authInterceptor = AuthInterceptor(
  tokenProvider: () async {
    // Return your auth token
    return await getAuthToken();
  },
);

client.addRequestInterceptor(authInterceptor);

Custom Interceptor

class CustomInterceptor implements RequestInterceptor {
  @override
  Future<void> onRequest(
    Uri url,
    HttpMethod method,
    Map<String, String> headers,
    dynamic body,
  ) async {
    // Add custom logic
    headers['X-Custom-Header'] = 'value';
  }
}

client.addRequestInterceptor(CustomInterceptor());

Retry Policy #

final config = ApiClientConfig(
  baseUrl: 'https://api.example.com',
  retryPolicy: RetryPolicy(
    maxRetries: 5,
    initialDelay: Duration(milliseconds: 500),
    maxDelay: Duration(seconds: 10),
    backoffMultiplier: 2.0,
    shouldRetry: (exception, retryCount) {
      // Custom retry logic
      return exception is NetworkException || 
             exception is TimeoutException;
    },
  ),
);

Rate Limiting #

final config = ApiClientConfig(
  baseUrl: 'https://api.example.com',
  maxRateLimitPerMinute: 60, // Max 60 requests per minute
);

Authentication Token Provider #

final config = ApiClientConfig(
  baseUrl: 'https://api.example.com',
  authTokenProvider: () async {
    // Fetch token from secure storage
    return await SecureStorage.getToken();
  },
);

Offline Queue #

When enabled, requests made while offline are automatically queued and retried when connection is restored:

final config = ApiClientConfig(
  baseUrl: 'https://api.example.com',
  enableOfflineQueue: true,
);

Advanced Features #

Custom Timeout Per Request #

final response = await client.get(
  '/slow-endpoint',
  timeout: Duration(seconds: 60),
);

Network Status Checking #

import 'package:http_nexus/http_nexus.dart';

final networkChecker = NetworkChecker();

// Check if connected
final isConnected = await networkChecker.isConnected();

// Listen to connectivity changes
networkChecker.onConnectivityChanged.listen((status) {
  print('Connectivity changed: $status');
});

// Wait for connection
await networkChecker.waitForConnection(
  timeout: Duration(seconds: 30),
);

🎯 Error Handling #

Smart API Client provides typed exceptions for different error scenarios:

try {
  final response = await client.get('/endpoint');
} on NetworkException catch (e) {
  // Network connectivity issues
  print('Network error: ${e.message}');
} on TimeoutException catch (e) {
  // Request timed out
  print('Timeout: ${e.message}');
} on ServerException catch (e) {
  // Server returned error status code
  print('Server error ${e.statusCode}: ${e.message}');
} on AuthenticationException catch (e) {
  // 401 - Authentication failed
  print('Auth failed: ${e.message}');
} on AuthorizationException catch (e) {
  // 403 - Insufficient permissions
  print('Access denied: ${e.message}');
} on RateLimitException catch (e) {
  // 429 - Rate limit exceeded
  print('Rate limit: ${e.message}');
} on ParseException catch (e) {
  // Failed to parse response
  print('Parse error: ${e.message}');
} on CancelledException catch (e) {
  // Request was cancelled
  print('Cancelled: ${e.message}');
} on ApiException catch (e) {
  // Catch-all for other API errors
  print('API error: ${e.message}');
}

API Reference #

ApiClientConfig #

Property Type Default Description
baseUrl String required Base URL for all requests
defaultTimeout Duration 30s Default request timeout
defaultHeaders Map<String, String> {} Headers added to all requests
retryPolicy RetryPolicy RetryPolicy() Configuration for retry logic
enableLogging bool false Enable request/response logging
enableOfflineQueue bool true Enable offline request queue
maxRateLimitPerMinute int? null Max requests per minute
authTokenProvider Function? null Function to provide auth token

RetryPolicy #

Property Type Default Description
maxRetries int 3 Maximum retry attempts
initialDelay Duration 1s Initial delay before retry
maxDelay Duration 30s Maximum delay between retries
backoffMultiplier double 2.0 Exponential backoff multiplier
shouldRetry Function - Custom retry decision logic

SmartApiClient Methods #

HTTP Methods

  • get(endpoint, {headers, queryParameters, timeout, cancelToken})
  • post(endpoint, {body, headers, queryParameters, timeout, cancelToken})
  • put(endpoint, {body, headers, queryParameters, timeout, cancelToken})
  • patch(endpoint, {body, headers, queryParameters, timeout, cancelToken})
  • delete(endpoint, {body, headers, queryParameters, timeout, cancelToken})

Interceptors

  • addRequestInterceptor(interceptor)
  • addResponseInterceptor(interceptor)

Cancellation

  • cancelRequest(cancelToken)

Cleanup

  • close() - Close client and cleanup resources

Best Practices #

1. Create a single client instance

Avoid creating multiple client instances. Instead, create one and reuse it throughout your app:

// Good: Singleton instance
class ApiService {
  static final ApiService _instance = ApiService._internal();
  factory ApiService() => _instance;
  
  late final SmartApiClient client;
  
  ApiService._internal() {
    client = SmartApiClient(config: ApiClientConfig(
      baseUrl: 'https://api.example.com',
    ));
  }
}

// Usage
final api = ApiService().client;

2. Use specific error types

Handle errors specifically rather than catching all exceptions:

// Good: Handle specific errors differently
try {
  await client.get('/data');
} on AuthenticationException {
  navigateToLogin();
} on NetworkException {
  showOfflineBanner();
}

3. Configure timeouts appropriately

Different endpoints may need different timeouts:

// Good: Adjust timeout based on expected response time
await client.get('/fast', timeout: Duration(seconds: 5));
await client.post('/slow-upload', timeout: Duration(minutes: 2));

4. Always clean up resources

Close the client when you're done with it:

@override
void dispose() {
  client.close();
  super.dispose();
}

Common Use Cases #

File Upload (with JSON)

final imageBase64 = base64Encode(imageBytes);
await client.post('/upload', body: {
  'filename': 'photo.jpg',
  'data': imageBase64,
});

Pagination

Future<List<Post>> loadPage(int page) async {
  final response = await client.get(
    '/posts',
    queryParameters: {
      'page': page,
      'limit': 20,
    },
  );
  return (response as List).map((json) => Post.fromJson(json)).toList();
}

Authentication Flow

Future<void> login(String email, String password) async {
  final response = await client.post('/auth/login', body: {
    'email': email,
    'password': password,
  });
  
  await saveToken(response['token']);
}

Testing #

The package includes comprehensive unit tests. Run them with:

flutter test

Example App #

Check out the example app in the /example folder for a complete working demonstration of all features.

Contributing #

Contributions are welcome! Please feel free to submit a Pull Request.

License #

This project is licensed under the MIT License - see the LICENSE file for details.

Support #

If you find this package helpful, please consider giving it a star on GitHub. If you encounter any issues or have questions, please open an issue on the repository.

Changelog #

See CHANGELOG.md for a list of changes in each version.


Built with Flutter

2
likes
120
points
20
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A lightweight but powerful HTTP client wrapper that simplifies API handling with automatic retries, error management, and network failure handling.

Repository (GitHub)
View/report issues

Topics

#http #api #rest-client #networking #flutter

License

MIT (license)

Dependencies

connectivity_plus, http, logger

More

Packages that depend on http_nexus