op_rest_api_client 0.14.0 copy "op_rest_api_client: ^0.14.0" to clipboard
op_rest_api_client: ^0.14.0 copied to clipboard

A Dart http client to send requests to REST API.

op_rest_api_client #

A lightweight, extensible Dart package for interacting with RESTful APIs.
Provides structured API requests, robust error handling, authentication support, and identity-based token management, while leveraging op_result for structured responses.


•	🔐 **Authentication support**: Integrates with `Identity` for token-based authentication, including automatic token refresh.
•	❌ **Robust error handling**: Utilizes `OpResult<T>` for structured success and failure responses.
•	🎯 **Type-safe API endpoints**: Encourages defining API endpoints using enums or constants for better maintainability.
•	🚧 **Automatic token refresh**: Automatically retries requests with a refreshed token upon receiving a `401 Unauthorized`.
•	✅ **Custom response validation**: Allows fine-grained validation via `customValidator`.

📦 Installation #

Add op_rest_api_client to your pubspec.yaml:

dependencies:
  op_rest_api_client: ^0.14.0

Or install via CLI:

dart pub add op_rest_api_client

🛠️ Usage #

1️⃣ Define API Endpoints as an Enum #

enum MyApiEndpoints {
  getUser,
  updateUser,
  deleteUser,
}

OpRestApiEndpoint getEndpoint(MyApiEndpoints endpoint) {
  switch (endpoint) {
    case MyApiEndpoints.getUser:
      return OpRestApiEndpoint('/user', OpRestApiClientMethods.get);
    case MyApiEndpoints.updateUser:
      return OpRestApiEndpoint('/user/update', OpRestApiClientMethods.put);
    case MyApiEndpoints.deleteUser:
      return OpRestApiEndpoint('/user/delete', OpRestApiClientMethods.delete);
  }
}

2️⃣ Initialize the API Client #

import 'package:op_rest_api_client/op_rest_api_client.dart';
import 'package:http/http.dart' as http;

final apiClient = OpRestApiClient<MyApiEndpoints>(
  baseUrl: "https://api.example.com",
  client: http.Client(),
);

3️⃣ Send API Requests #

🔹 GET Request

final result = await apiClient.send(
  endpoint: getEndpoint(MyApiEndpoints.getUser),
  identity: userIdentity, // Optional authentication
);

if (result.isSuccess) {
  print("User data: \${result.data.body}");
} else {  
  print("Error: \${result.error.getErrorMessage()}");
}

🔹 POST Request (With Body)

final newUser = {
  'name': 'John Doe',
  'email': '[email protected]',
};

final result = await apiClient.send(
  endpoint: getEndpoint(MyApiEndpoints.updateUser), 
  identity: userIdentity,
  body: newUser,
);

if (result.isSuccess) {
  print("User updated successfully!");
} else {
  print("Error: \${result.error.getErrorMessage()}");
}

🔹 DELETE Request

final result = await apiClient.send(
  endpoint: getEndpoint(MyApiEndpoints.deleteUser), 
  identity: userIdentity,
);

if (result.isSuccess) {
  print("User deleted!");
} else {
  print("Error: \${result.error.getErrorMessage()}");
}

📌 Authentication & Token Refresh #

The client supports authentication via OpRestApiIdentity, handling token refresh automatically.

class MyApiIdentity extends OpRestApiIdentity<String> {
  final String accessToken;
  final String refreshToken;

  MyApiIdentity({
    required this.accessToken,
    required this.refreshToken,
  });

  @override
  String get identityData => accessToken;

  @override
  bool isValid() => accessToken.isNotEmpty;

  @override
  bool isExpired() {
    // Example logic for expiration check (adjust as needed)
    return false;
  }

  @override
  String authorizationHeader() => "Bearer $accessToken";

  @override
  Future<OpRestApiIdentity<String>?> refresh() async {
    // Refresh token logic (example)
    return MyApiIdentity(
      accessToken: "newAccessToken",
      refreshToken: "newRefreshToken",
    );
  }
}

final userIdentity = MyApiIdentity(
  accessToken: "abc123",
  refreshToken: "refresh123",
);

If a request fails due to an expired token (401):

  • The client automatically attempts token refresh once.
  • If the refresh succeeds, the original request is retried automatically using the new token.
  • If the refresh fails, an unauthenticated error (OpError(AuthError.unauthenticated)) is returned.

❌ Error Handling #

All API responses are wrapped in OpResult<http.Response>, which indicates success or failure.


📌 Error Handling #

Usage of customValidator:

OpResult<http.Response, MyCustomError>? myValidator(http.Response response) {
  if (response.statusCode == 200 || response.statusCode == 202) {
    return OpResult.success(response);
  }
  if (response.statusCode == 404) {
    return OpResult.failure(OpError(type: MyCustomError.notFound));
  }
  return null; // Fallback to default handling
}

final result = await apiClient.send(
  endpoint: getEndpoint(MyApiEndpoints.getUser),
  customValidator: myValidator,
);

🛠 Advanced Configuration #

🌐 Custom Headers #

await apiClient.send(
  endpoint: getEndPoint(MyApiEndpoints.getUser),
  headers: {
    "X-Custom-Header": "value",
  },
);

📜 Enforcing Response Type #

If an API is expected to return a certain content type (e.g. JSON) but sometimes it doesn't, then the optional responseMapper parameter can be used to enforce that format:

final apiClient = OpRestApiClient<MyApiEndpoints>(
  baseUrl: "https://api.example.com",
  client: http.Client(),
  responseMapper: (response) {
    // Example: Ensure response is always JSON
    if (!response.headers['content-type']?.contains('application/json') ?? true) {
      throw FormatException('Invalid response format');
    }
    return response;
  },
);

🚀 Why Use op_rest_api_client? #

Structured API calls → No need to manage HTTP manually.
Authentication & token refresh → Handles 401 errors automatically.
Strong typing with enums → Prevents invalid API endpoints.
Full OpResult support → Clear success/failure responses.
Custom error handling → Map HTTP codes to app-specific errors.


📌 Versioning & Changelog #

For release history and breaking changes, check the CHANGELOG.


⚖ License #

This project is licensed under the BSD 3-Clause License.

0
likes
0
points
7
downloads

Publisher

verified publishercantini.dev

Weekly Downloads

A Dart http client to send requests to REST API.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

http, op_result

More

Packages that depend on op_rest_api_client