Orientação gerada a partir de informações públicas. Apenas para referência.
Um pacote Flutter/Dart que fornece uma abstração limpa para interagir com APIs REST. Simplifica as requisições HTTP enquanto lida com desafios comuns, como gerenciamento de erros e autenticação JWT com suporte automático ao refresh do token. Projetado para simplificar a comunicação com APIs em múltiplas plataformas, reduzindo o código repetitivo e aumentando a confiabilidade nas operações de rede. Ideal para aplicativos que exigem integração segura e consistente com o backend.
Casos de uso
Integração com APIs REST autenticadas
Tratar erros HTTP com elegância
Automatizando a atualização do token JWT
Construindo integrações de backend escaláveis
Gerenciando o ciclo de vida da solicitação da API
Suporte a chamadas de rede multiplataforma
Principais recursos
Manipulação integrada de JWT e token de atualização
Tratamento abrangente de exceções
Compatibilidade multiplataforma
Interface de cliente de API simples e reutilizável
Interceptação automática de solicitações
URL base e cabeçalhos configuráveis
Indicado para
Aplicativos Flutter com backend REST
Projetos que exigem acesso seguro à API
Desenvolvedores procurando reduzir o boilerplate de rede
Equipes que desenvolvem aplicativos multiplataforma
Aplicativos usando autenticação baseada em JWT
Considerações
Requer configuração correta do token JWT
Depende do pacote externo http
Pode ser necessário mapeamento personalizado de erros
Limitado a endpoints do estilo REST
Não adequado para protocolos não HTTP
O fluxo de autenticação deve estar alinhado com a lógica do servidor
README original
Snapshot do README original do repositório-fonte vinculado. Consulte o repositório para o conteúdo mais recente.
Rest API Client
A production-ready HTTP client for Flutter applications that simplifies REST API communication with built-in support for JWT authentication, automatic token refresh, response caching, retry logic, and comprehensive error handling.
Features
JWT Authentication - Automatic token management with secure storage (Keychain/EncryptedSharedPreferences)
Token Refresh - Two strategies: response-and-retry or preemptive refresh before expiry
Response Caching - Intelligent caching with configurable expiration
Retry Logic - Exponential backoff for failed requests
// GET requestfinal result = await client.get('/users');
// GET with query parametersfinal result = await client.get('/users', queryParameters: {'page': 1, 'limit': 10});
// POST requestfinal result = await client.post('/users', data: {'name': 'John', 'email': 'john@example.com'});
// PUT requestfinal result = await client.put('/users/1', data: {'name': 'John Updated'});
// PATCH requestfinal result = await client.patch('/users/1', data: {'name': 'John Patched'});
// DELETE requestfinal result = await client.delete('/users/1');
// HEAD requestfinal result = await client.head('/users/1');
With Type Conversion
Use onSuccess to parse responses into typed objects:
final result = await client.get<User>(
'/users/1',
onSuccess: (data) => User.fromJson(data),
);
if (result.hasData) {
User user = result.data!;
print(user.name);
}
Per-Request Options
final result = await client.get(
'/users',
options: RestApiClientRequestOptions(
headers: {'X-Custom': 'value'},
contentType: 'application/json',
requiresAuth: false, // Skip authentication for this request
silentException: true, // Don't broadcast exceptions
),
);
Caching Strategies
Cache-First (Stale-While-Revalidate)
Returns cached data immediately, then fetches fresh data:
awaitfor (final result in client.getStreamed('/users')) {
if (result.hasData) {
// First emission: cached data (if available)// Second emission: fresh network dataupdateUI(result.data);
}
}
Cache-Only
Get data from cache only (no network request):
final result = await client.getCached('/users');
if (result.hasData) {
print('Cached data: ${result.data}');
}
Cache-Or-Network
Try cache first, fall back to network:
final result = await client.getCachedOrNetwork('/users');
Custom Cache Duration
final result = await client.get(
'/users',
cacheLifetimeDuration: Duration(hours: 1),
);
Authentication
Login Flow
// 1. Make login requestfinal loginResult = await client.post('/auth/login', data: {
'email': 'user@example.com',
'password': 'password123',
});
// 2. Authorize the client with received tokensif (loginResult.hasData) {
await client.authorize(
jwt: loginResult.data['accessToken'],
refreshToken: loginResult.data['refreshToken'],
);
}
// 3. All subsequent requests will include the JWTfinal userResult = await client.get('/users/me');
Check Authorization Status
final isLoggedIn = await client.isAuthorized();
Logout
await client.unAuthorize();
await client.clearStorage(); // Clear tokens and cached data
Error Handling
Result Object
All requests return a Result<T> object:
final result = await client.get('/users');
// Check for dataif (result.hasData) {
print(result.data);
}
// Check for errorsif (result.isError) {
print(result.exception);
}
// Check specific error typesif (result.isConnectionError) {
print('No internet connection');
}
// Access HTTP statusprint(result.statusCode); // e.g., 200, 404, 500print(result.statusMessage); // e.g., "OK", "Not Found"
Exception Types
Exception
HTTP Status
Description
ValidationException
400, 404, 422
Input validation errors
UnauthorizedException
401
Authentication required
ForbiddenException
403
Access denied
ServerErrorException
500, 502
Server-side errors
NetworkErrorException
-
Connection issues
Global Exception Stream
Listen to all exceptions across the app:
client.exceptionHandler.exceptions.stream.listen((exception) {
if (exception isUnauthorizedException) {
// Redirect to login
navigatorKey.currentState?.pushReplacementNamed('/login');
} elseif (exception isNetworkErrorException) {
// Show offline bannershowSnackBar('No internet connection');
}
});
Suppress Exceptions
// Suppress for a single requestfinal result = await client.get(
'/users',
options: RestApiClientRequestOptions(silentException: true),
);
File Downloads
final result = await client.download(
'/files/document.pdf',
'/path/to/save/document.pdf',
onReceiveProgress: (received, total) {
final progress = (received / total * 100).toStringAsFixed(0);
print('Download progress: $progress%');
},
);
Headers
// Set content type
client.setContentType('application/json');
// Set language
client.setAcceptLanguageHeader('en');
// Add custom header
client.addOrUpdateHeader(key: 'X-Api-Key', value: 'your-api-key');
// Access current headersprint(client.headers);