IwsHttp
Library to facilitate HTTP requests with REST APIs in Dart/Flutter. Provides JWT authentication, error handling, file upload, connection pooling/client injection, and convenient helpers for building API clients.
Features
- Authentication with JWT (Bearer) and/or API Key
- HTTP error handling with typed custom exceptions retaining full response payloads
- File upload (multipart/form-data) supporting device paths, bytes, custom MIME types, and configurable field names
- Support for GET, POST, PUT, PATCH, DELETE
- Persistent HTTP client with connection pooling and custom
http.Clientinjection (for tests withMockClient) - Automatic path normalization and dynamic path generation helper for RESTful endpoints
- Session management utilities (
updateBearerToken,clearSession)
Getting started
Initialize the library (singleton):
IwsHttp.setup(
authority: 'api.mydomain.com',
apiKey: 'my_secret_api_key',
basePath: 'api/v1',
secureConnection: true,
bearerToken: 'my_secret_token',
timeout: 10, // seconds
defaultHeaders: {
'Accept-Language': 'es-AR',
},
);
Or create a new instance:
final client = IwsHttp.newInstance(
authority: 'api.mydomain.com',
apiKey: 'my_secret_api_key',
basePath: 'api/v1',
secureConnection: true,
bearerToken: 'my_secret_token',
timeout: 10,
);
Usage
Import the package:
import 'package:iws_http/iws_http.dart';
POST request
final response = await IwsHttp().post(
path: 'login',
body: {'email': 'user@example.com', 'password': '1234'},
auth: false, // Set to false if endpoint does not require JWT
);
GET request
final data = await IwsHttp().get(
path: 'users',
queryParameters: {'page': '1'},
);
PUT request
await IwsHttp().put(
path: 'users/1',
body: {'name': 'New Name'},
);
PATCH request
await IwsHttp().patch(
path: 'users/1',
body: {'email': 'new@email.com'},
);
DELETE request
await IwsHttp().delete(
path: 'users/1',
);
File upload (multipart/form-data)
// From device path
final file = FileDto(
path: '/path/to/avatar.jpg',
contentType: 'image/jpeg',
);
final result = await IwsHttp().upload(
path: 'users/avatar',
file: file,
fieldName: 'avatar', // Custom field name (defaults to 'file')
fields: {'userId': '123'},
);
// Or from in-memory bytes
final fileFromBytes = FileDto(
bytes: uint8ListData,
name: 'avatar.png',
contentType: 'image/png',
);
Generate RESTful endpoint paths
final path = IwsHttp().generatePath(
path: 'user/{userId}/payment/{paymentId}',
pathParam: {'userId': 123, 'paymentId': 456},
);
// Result: 'user/123/payment/456'
Testing with MockClient
Inject a custom http.Client for fast, hermetic unit tests:
import 'package:http/testing.dart';
import 'package:http/http.dart' as http;
import 'package:iws_http/iws_http.dart';
final mockClient = MockClient((request) async {
return http.Response('{"status": "ok"}', 200);
});
final client = IwsHttp.newInstance(
authority: 'api.example.com',
client: mockClient,
);
API Reference
Methods
IwsHttp.setup(...)
Initializes the singleton instance. Call this once at app startup. Supports optional client: http.Client and defaultAuth: bool.
IwsHttp.newInstance(...)
Creates a new, independent instance. Supports optional client: http.Client and defaultAuth: bool.
IwsHttp()
Returns the configured singleton instance.
post({required String path, body, ...})
Sends a POST request. body is encoded as JSON. Returns decoded response.
get({required String path, ...})
Sends a GET request. Returns decoded response.
put({required String path, body, ...})
Sends a PUT request. body is encoded as JSON.
patch({required String path, body, ...})
Sends a PATCH request. body is encoded as JSON.
delete({required String path, ...})
Sends a DELETE request. Optionally accepts a body.
upload({required String path, required FileDto file, String fieldName = 'file', int? timeout, ...})
Uploads a file using multipart/form-data. Accepts file path or bytes, optional MIME contentType, and custom field name.
generatePath({required String path, Map<String, dynamic>? pathParam, String? id})
Generates a RESTful endpoint path by URL-encoding and replacing {param} segments.
updateBearerToken(String? token)
Updates the bearer token for subsequent authenticated requests on this instance.
clearSession()
Clears authentication credentials (bearerToken and apiKey).
Error Handling
All methods throw custom exceptions extending ApiException for HTTP errors, retaining the status code and decoded response body:
ApiException(base, includeshttpCode,error, andresponse)BadRequestException(400)UnauthorisedException(401/403)DataNotFoundException(404)FormRequestException(422, includesinputErrorsandresponse)FetchDataException(500, 429, connection errors)
try {
final users = await IwsHttp().get(path: 'users');
} on FormRequestException catch (e) {
print('Validation errors: ${e.inputErrors}');
} on UnauthorisedException catch (e) {
print('Auth error: ${e.error}');
} on ApiException catch (e) {
print('API error [${e.httpCode}]: ${e.error}, payload: ${e.response}');
}