### API Usage Example Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Demonstrates how to instantiate the ApiConnector and use its endpoints to list, get, and create users. ```dart final api = ApiConnector(token: 'my-token'); // List users final users = await api.users.list(); print(users.jsonList()); // Get a specific user final user = await api.users.get(42); print(user.json()['name']); // Create a user final created = await api.users.create(name: 'Alice', email: 'alice@example.com'); print(created.json()['id']); ``` -------------------------------- ### Quick Start: Forge API Integration Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Demonstrates how to set up a custom connector for the Forge API and send a basic GET request to retrieve servers. ```dart import 'package:lucky_dart/lucky_dart.dart'; // 1. Define the connector class ForgeConnector extends Connector { final String _token; ForgeConnector({required String token}) : _token = token; @override String resolveBaseUrl() => 'https://forge.laravel.com/api/v1'; @override Authenticator? get authenticator => TokenAuthenticator(_token); } // 2. Define a request class GetServersRequest extends Request { @override String get method => 'GET'; @override String resolveEndpoint() => '/servers'; } // 3. Send it void main() async { final forge = ForgeConnector(token: 'my-api-token'); final response = await forge.send(GetServersRequest()); for (final server in response.jsonList()) { print(server['name']); } } ``` -------------------------------- ### Initialize Connector and Send Request Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Instantiate a ForgeConnector with a token and send a GetServersRequest. The response can then be processed to get a list of JSON objects. ```dart final api = ForgeConnector(token: myToken); final servers = await api.send(GetServersRequest()); print(servers.jsonList()); ``` -------------------------------- ### Rate Limit Throttle Policy Example Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Configures a RateLimitThrottlePolicy to enforce a maximum of 10 requests per second. The policy is attached to a custom connector. ```dart class WeatherConnector extends Connector { // Max 10 requests per second final _throttle = RateLimitThrottlePolicy( maxRequests: 10, windowDuration: Duration(seconds: 1), ); @override String resolveBaseUrl() => 'https://api.openweathermap.org'; @override ThrottlePolicy? get throttlePolicy => _throttle; } ``` -------------------------------- ### Custom Request: Get Repository Details Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Defines a request to fetch repository details from GitHub, including custom query parameters and headers. ```dart class GetRepositoryRequest extends Request { final String owner; final String repo; GetRepositoryRequest(this.owner, this.repo); @override String get method => 'GET'; @override String resolveEndpoint() => '/repos/$owner/$repo'; @override Map? queryParameters() => {'per_page': 100}; @override Map? headers() => {'X-Custom': 'value'}; } ``` -------------------------------- ### Runtime Authentication Update Source: https://github.com/owlnext-fr/lucky/blob/main/README.md The `authenticator` getter can be re-evaluated at runtime. This allows updating authentication credentials after initial setup, for example, after a login process. ```dart class ApiConnector extends Connector { Authenticator? _auth; // Public setter so callers in other files can update auth at runtime set authenticatorOverride(Authenticator? auth) => _auth = auth; @override Authenticator? get authenticator => _auth; @override String resolveBaseUrl() => 'https://api.example.com'; } // Usage final api = ApiConnector(); // No auth yet — login endpoint skips it final login = await api.send(LoginRequest(email: 'user@example.com', password: 'secret')); final token = login.json()['token'] as String; // Set token for all subsequent requests via the public setter api.authenticatorOverride = TokenAuthenticator(token); final profile = await api.send(GetProfileRequest()); // now authenticated ``` -------------------------------- ### List Users Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Retrieves a list of all users. This is a GET request to the /users endpoint. ```APIDOC ## GET /users ### Description Retrieves a list of all users. ### Method GET ### Endpoint /users ### Response #### Success Response (200) - **users** (List) - A list of user objects. ``` -------------------------------- ### Get User Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Retrieves details for a specific user by their ID. This is a GET request to the /users/{id} endpoint. ```APIDOC ## GET /users/{id} ### Description Retrieves details for a specific user by their ID. ### Method GET ### Endpoint /users/{id} #### Path Parameters - **id** (int) - Required - The unique identifier of the user. ### Response #### Success Response (200) - **user** (Object) - The user object containing user details. ``` -------------------------------- ### Configuring Exponential Backoff Retry Policy Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Implement ExponentialBackoffRetryPolicy to automatically retry failed requests with increasing delays. This example shows a custom configuration with 4 total attempts and a 1-second initial delay. ```dart class MyConnector extends Connector { @override String resolveBaseUrl() => 'https://api.example.com'; // 4 total attempts (1 initial + 3 retries), start at 1s @override RetryPolicy? get retryPolicy => const ExponentialBackoffRetryPolicy( maxAttempts: 4, initialDelay: Duration(seconds: 1), ); } ``` -------------------------------- ### Define User API Endpoints Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Defines request classes for listing, getting, and creating users, along with an endpoint class to manage these requests. ```dart // Requests class ListUsersRequest extends Request { @override String get method => 'GET'; @override String resolveEndpoint() => '/users'; } class GetUserRequest extends Request { final int id; GetUserRequest(this.id); @override String get method => 'GET'; @override String resolveEndpoint() => '/users/$id'; } class CreateUserRequest extends Request with HasJsonBody { final String name; final String email; CreateUserRequest({required this.name, required this.email}); @override String get method => 'POST'; @override String resolveEndpoint() => '/users'; @override Map jsonBody() => {'name': name, 'email': email}; } // Endpoint class class UsersEndpoint { final Connector _connector; UsersEndpoint(this._connector); Future list() => _connector.send(ListUsersRequest()); Future get(int id) => _connector.send(GetUserRequest(id)); Future create({required String name, required String email}) => _connector.send(CreateUserRequest(name: name, email: email)); } ``` -------------------------------- ### Custom Connector: GitHub API Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Example of a custom connector for the GitHub API, overriding default headers and disabling exceptions for non-2xx status codes. ```dart class GithubConnector extends Connector { final String _token; GithubConnector(this._token); @override String resolveBaseUrl() => 'https://api.github.com'; @override Map? defaultHeaders() => { 'Accept': 'application/vnd.github+json', 'X-GitHub-Api-Version': '2022-11-28', }; @override Authenticator? get authenticator => TokenAuthenticator(_token); // Disable exceptions for non-2xx — handle status codes manually @override bool get throwOnError => false; } ``` -------------------------------- ### Customizing Retry Status Codes with Exponential Backoff Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Customize which HTTP status codes trigger a retry when using ExponentialBackoffRetryPolicy. This example limits retries to gateway errors (503, 504). ```dart @override RetryPolicy? get retryPolicy => const ExponentialBackoffRetryPolicy( maxAttempts: 3, retryOnStatusCodes: {503, 504}, // only retry gateway errors ); ``` -------------------------------- ### Parsing a List of Models with `as()` Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Demonstrates how to use `as()` to parse a JSON list response into a list of custom model objects. ```dart final response = await connector.send(GetUsersRequest()); final users = response.as( (r) => r.jsonList().map((e) => User.fromJson(e as Map)).toList(), ); print(users.length); // 10 ``` -------------------------------- ### Basic Authentication Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Implement BasicAuthenticator with a username and password for basic authentication. ```dart class MyConnector extends Connector { @override Authenticator? get authenticator => BasicAuthenticator('user', 'password'); // Adds: Authorization: Basic dXNlcjpwYXNzd29yZA== } ``` -------------------------------- ### Create User Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Creates a new user with the provided name and email. This is a POST request to the /users endpoint with a JSON body. ```APIDOC ## POST /users ### Description Creates a new user with the provided name and email. ### Method POST ### Endpoint /users #### Request Body - **name** (string) - Required - The name of the user. - **email** (string) - Required - The email address of the user. ### Response #### Success Response (200) - **id** (int) - The unique identifier of the newly created user. ``` -------------------------------- ### Create Post Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Creates a new post with a title and content, sent as JSON. This is a POST request to the /posts endpoint. ```APIDOC ## POST /posts ### Description Creates a new post with a title and content, sent as JSON. ### Method POST ### Endpoint /posts #### Request Body - **title** (string) - Required - The title of the post. - **content** (string) - Required - The content of the post. ### Response #### Success Response (200) - **id** (int) - The unique identifier of the newly created post. ``` -------------------------------- ### Configuring Logging in Lucky Connector Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Enable logging and define a custom log callback for a Lucky connector. This allows integration with any logging system by providing a LuckyLogCallback. ```dart class MyConnector extends Connector { @override bool get enableLogging => true; @override LuckyLogCallback get onLog => ({required message, level, context}) { // Wire to your favourite logger print('[$level] $message'); }; // More verbose structured output — use kDebugMode in Flutter, or true/false in Dart @override bool get debugMode => true; @override LuckyDebugCallback get onDebug => ({required event, message, data}) { print('DEBUG [$event] $message\n$data'); }; } ``` -------------------------------- ### Login Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Authenticates a user with email and password, sent as form data. This is a POST request to the /login endpoint. ```APIDOC ## POST /login ### Description Authenticates a user with email and password, sent as form data. ### Method POST ### Endpoint /login #### Request Body - **email** (string) - Required - The user's email address. - **password** (string) - Required - The user's password. ### Response #### Success Response (200) - **token** (string) - The authentication token. ``` -------------------------------- ### Configuring Immediate Retry Policy Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Implement ImmediateRetryPolicy for retries with no delay. This is useful for very transient errors that are expected to resolve within milliseconds. ```dart @override RetryPolicy? get retryPolicy => const ImmediateRetryPolicy(maxAttempts: 2); ``` -------------------------------- ### API Connector Implementation Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Implements the Connector class to resolve the base URL and provide authentication. It also exposes endpoint accessors. ```dart class ApiConnector extends Connector { ApiConnector({required String token}) : _token = token; final String _token; @override String resolveBaseUrl() => 'https://api.example.com'; @override Authenticator? get authenticator => TokenAuthenticator(_token); // Endpoint accessors late final users = UsersEndpoint(this); } ``` -------------------------------- ### Upload File Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Uploads a file as a binary stream. This is a PUT request to the /upload endpoint. ```APIDOC ## PUT /upload ### Description Uploads a file as a binary stream. ### Method PUT ### Endpoint /upload #### Request Body - **file** (Stream) - Required - The file content as a binary stream. ### Response #### Success Response (200) - **url** (string) - The URL where the file has been uploaded. ``` -------------------------------- ### Handling LuckyThrottleException Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Demonstrates how to catch and handle a LuckyThrottleException, which is thrown when rate limits are exceeded and the maxWaitTime is hit. This allows for graceful failure or alternative actions. ```dart try { final r = await connector.send(MyRequest()); } on LuckyThrottleException catch (e) { // Rate limit exceeded and maxWaitTime was hit print('Too many requests: ${e.message}'); } ``` -------------------------------- ### Submit Order Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Submits an order with the specified order ID, sent as XML. This is a POST request to the /orders endpoint. ```APIDOC ## POST /orders ### Description Submits an order with the specified order ID, sent as XML. ### Method POST ### Endpoint /orders #### Request Body - **orderId** (string) - Required - The ID of the order. ### Response #### Success Response (200) - **status** (string) - The status of the order submission. ``` -------------------------------- ### Rate Limit Throttle Policy with Max Wait Time Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Sets up a RateLimitThrottlePolicy with a maximum wait time of 200 milliseconds. Requests exceeding this wait time will fail fast by throwing a LuckyThrottleException. ```dart final _throttle = RateLimitThrottlePolicy( maxRequests: 5, windowDuration: Duration(seconds: 1), maxWaitTime: Duration(milliseconds: 200), // throw instead of waiting > 200ms ); ``` -------------------------------- ### Combining RateLimitThrottlePolicy and RetryPolicy Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Simultaneously apply RateLimitThrottlePolicy and ExponentialBackoffRetryPolicy to a connector. The throttle policy is always evaluated before any retry attempt. ```dart class ApiConnector extends Connector { // Throttle: max 5 requests/second, never wait more than 500ms final _throttle = RateLimitThrottlePolicy( maxRequests: 5, windowDuration: Duration(seconds: 1), maxWaitTime: Duration(milliseconds: 500), ); @override String resolveBaseUrl() => 'https://api.example.com'; @override ThrottlePolicy? get throttlePolicy => _throttle; // Retry: up to 3 attempts on 429/5xx and network errors @override RetryPolicy? get retryPolicy => const ExponentialBackoffRetryPolicy(); } ``` -------------------------------- ### TokenBucketThrottlePolicy with Max Wait Time Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Configure TokenBucketThrottlePolicy to fail fast instead of blocking when the bucket is too empty by setting a maxWaitTime. ```dart final _throttle = TokenBucketThrottlePolicy( capacity: 5, refillRate: 2.0, maxWaitTime: Duration(milliseconds: 500), ); ``` -------------------------------- ### Configuring Linear Backoff Retry Policy Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Use LinearBackoffRetryPolicy for retries with a fixed delay between each attempt. This is suitable when the service recovery time is predictable. ```dart @override RetryPolicy? get retryPolicy => const LinearBackoffRetryPolicy( maxAttempts: 4, delay: Duration(seconds: 2), // always 2s between attempts ); ``` -------------------------------- ### Add lucky_dart Dependency Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Add the lucky_dart package to your project's dependencies in pubspec.yaml. ```yaml dependencies: lucky_dart: ^1.0.0 ``` -------------------------------- ### Parsing Response into a Model with `as()` Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Use the `as()` method with a custom transformer to map raw JSON response data directly into your own model classes. ```dart class User { final int id; final String name; final String email; User.fromJson(Map json) : id = json['id'] as int, name = json['name'] as String, email = json['email'] as String; } final response = await connector.send(GetUserRequest(42)); final user = response.as((r) => User.fromJson(r.json())); print(user.name); // Alice ``` -------------------------------- ### Jittered Retry Policy for Cloud API Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Combines exponential backoff with equal jitter. Suitable for interacting with cloud APIs that have specific rate limiting or backoff requirements. ```dart JitteredRetryPolicy( inner: const ExponentialBackoffRetryPolicy(maxAttempts: 4), maxJitter: Duration(milliseconds: 500), strategy: JitterStrategy.equal, // [base + maxJitter/2, base + maxJitter] ) ``` -------------------------------- ### ConcurrencyThrottlePolicy with Max Wait Time Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Configure ConcurrencyThrottlePolicy with a maxWaitTime to throw an exception if no slot is available within the specified duration, preventing indefinite blocking. ```dart final _throttle = ConcurrencyThrottlePolicy( maxConcurrent: 3, maxWaitTime: Duration(seconds: 2), // throw if no slot available within 2s ); ``` -------------------------------- ### Custom Header Authentication Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Use HeaderAuthenticator to add custom headers with API keys or other credentials. ```dart class MyConnector extends Connector { @override Authenticator? get authenticator => HeaderAuthenticator('X-Api-Key', 'secret'); // Adds: X-Api-Key: secret } ``` -------------------------------- ### Response Body Parsing Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Offers methods to parse the response body into common types like JSON, text, or bytes. `as()` allows custom transformations. ```dart // Parsing — throw LuckyParseException on type mismatch r.json() // Map r.jsonList() // List r.text() // String r.bytes() // List // Custom transformation with as() final user = r.as((res) => User.fromJson(res.json())); ``` -------------------------------- ### API Key in Query Parameter Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Use QueryAuthenticator to append API keys as query parameters to requests. This is done via `toQueryMap()` in `defaultQuery()`. ```dart class WeatherConnector extends Connector { final _auth = QueryAuthenticator('appid', 'my-api-key'); @override Map? defaultQuery() => _auth.toQueryMap(); // Appends: ?appid=my-api-key to every request } ``` -------------------------------- ### Jittered Retry Policy for Scraping Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Adds a bounded random delay to a linear backoff policy. Useful for scraping to avoid overwhelming a service. ```dart JitteredRetryPolicy( inner: LinearBackoffRetryPolicy(delay: Duration(seconds: 10)), maxJitter: Duration(seconds: 2), strategy: JitterStrategy.full, // [base, base + maxJitter] ) ``` -------------------------------- ### Response Status and Content Type Checks Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Provides helper properties to easily check the status code range and content type of a response. ```dart final r = await connector.send(GetUsersRequest()); // Status checks r.isSuccessful // 200-299 r.isClientError // 400-499 r.isServerError // 500+ r.isRedirect // 300-399 r.statusCode // int // Content type r.isJson // Content-Type contains application/json r.isXml // Content-Type contains xml r.isHtml // Content-Type contains text/html ``` -------------------------------- ### Custom LuckyLogCallback Implementation Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Define a custom logger using the LuckyLogCallback type for integration with external logging libraries like Talker. ```dart final LuckyLogCallback myLogger = ({required message, level, context}) { talker.log(message, logLevel: level); }; ``` -------------------------------- ### Send Raw Text Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Sends raw text content. This is a POST request to the /raw endpoint with plain text body. ```APIDOC ## POST /raw ### Description Sends raw text content. ### Method POST ### Endpoint /raw #### Request Body - **content** (string) - Required - The raw text content to send. ### Response #### Success Response (200) - **message** (string) - A confirmation message. ``` -------------------------------- ### Bearer Token Authentication Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Use TokenAuthenticator for bearer tokens. You can optionally specify a custom prefix. ```dart class MyConnector extends Connector { @override Authenticator? get authenticator => TokenAuthenticator('my-token'); // Adds: Authorization: Bearer my-token } // Custom prefix TokenAuthenticator('my-token', prefix: 'Token') // Adds: Authorization: Token my-token ``` -------------------------------- ### Jittered Retry Policy with Fixed Seed Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Configures a jittered retry policy with a specific random seed for deterministic testing. Ensures reproducible delays during tests. ```dart JitteredRetryPolicy( inner: const LinearBackoffRetryPolicy(), maxJitter: Duration(seconds: 1), random: Random(42), // fixed seed → reproducible delays ) ``` -------------------------------- ### Upload Avatar Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Uploads a user's avatar image. This is a POST request to the /users/{userId}/avatar endpoint with multipart data. ```APIDOC ## POST /users/{userId}/avatar ### Description Uploads a user's avatar image. ### Method POST ### Endpoint /users/{userId}/avatar #### Path Parameters - **userId** (string) - Required - The ID of the user whose avatar is being uploaded. #### Request Body - **avatar** (File) - Required - The avatar image file. ``` -------------------------------- ### TokenBucketThrottlePolicy for Controlled Bursts Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Implement a token bucket policy to allow controlled bursts of requests. This is suitable for APIs that model their limits using token buckets, like GitHub and Stripe. ```dart class MyConnector extends Connector { // 10 req/s sustained, burst up to 20 final _throttle = TokenBucketThrottlePolicy( capacity: 20, refillRate: 10.0, // tokens refilled per second ); @override ThrottlePolicy? get throttlePolicy => _throttle; } ``` -------------------------------- ### Plain Text Request Body Mixin Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Defines a SendRawRequest using the HasTextBody mixin for sending plain text data. Sets Content-Type to text/plain. ```dart class SendRawRequest extends Request with HasTextBody { final String content; SendRawRequest(this.content); @override String get method => 'POST'; @override String resolveEndpoint() => '/raw'; @override String textBody() => content; } ``` -------------------------------- ### Custom Retry Policy: Only On 503 Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Implements a custom retry policy that only retries on HTTP 503 Service Unavailable status codes. It defines a maximum of 5 attempts and a delay that increases with each attempt. ```dart class OnlyOn503RetryPolicy extends RetryPolicy { const OnlyOn503RetryPolicy(); @override int get maxAttempts => 5; @override bool shouldRetryOnResponse(LuckyResponse response, int attempt) => response.statusCode == 503; @override bool shouldRetryOnException(LuckyException exception, int attempt) => false; @override Duration delayFor(int attempt) => Duration(seconds: attempt); // 1s, 2s, 3s… } ``` -------------------------------- ### Handling Typed Exceptions for Non-2xx Responses Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Use this snippet to catch specific exceptions thrown by Lucky for different HTTP error status codes when throwOnError is true. It covers common errors like NotFound, Unauthorized, Validation, Timeout, Connection, and general Lucky exceptions. ```dart try { final r = await connector.send(GetUserRequest(42)); print(r.json()['name']); } on NotFoundException catch (e) { // 404 — e.statusCode == 404 print('User not found: ${e.message}'); } on UnauthorizedException catch (e) { // 401 print('Authentication required'); } on ValidationException catch (e) { // 422 — e.errors contains the field errors map e.errors?.forEach((field, messages) { print('$field: $messages'); }); } on LuckyTimeoutException catch (e) { // Connection or read timeout print('Request timed out'); } on ConnectionException catch (e) { // Network unreachable, DNS failure, etc. print('Network error: ${e.message}'); } on LuckyException catch (e) { // Any other HTTP error (5xx, etc.) print('HTTP ${e.statusCode}: ${e.message}'); } ``` -------------------------------- ### XML Request Body Mixin Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Defines a SubmitOrderRequest using the HasXmlBody mixin for sending XML data. Sets Content-Type and Accept to application/xml. ```dart class SubmitOrderRequest extends Request with HasXmlBody { final String orderId; SubmitOrderRequest(this.orderId); @override String get method => 'POST'; @override String resolveEndpoint() => '/orders'; @override String xmlBody() => ''' $orderId'''; } ``` -------------------------------- ### JSON Request Body Mixin Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Defines a CreatePostRequest using the HasJsonBody mixin for sending JSON data. Automatically sets Content-Type and Accept headers to application/json. ```dart class CreatePostRequest extends Request with HasJsonBody { final String title; final String content; // note: don't name this 'body' — conflicts with body() from HasJsonBody CreatePostRequest({required this.title, required this.content}); @override String get method => 'POST'; @override String resolveEndpoint() => '/posts'; @override Map jsonBody() => {'title': title, 'body': content}; } ``` -------------------------------- ### Binary Stream Request Body Mixin Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Defines an UploadFileRequest using the HasStreamBody mixin for sending binary data. Sets Content-Type to application/octet-stream and includes Content-Length. ```dart class UploadFileRequest extends Request with HasStreamBody { final File file; UploadFileRequest(this.file); @override String get method => 'PUT'; @override String resolveEndpoint() => '/upload'; @override int get contentLength => file.lengthSync(); @override Stream> streamBody() => file.openRead(); } ``` -------------------------------- ### Multipart Request Body Mixin for File Upload Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Defines an UploadAvatarRequest using the HasMultipartBody mixin for file uploads. Sets Content-Type to multipart/form-data. ```dart class UploadAvatarRequest extends Request with HasMultipartBody { final File file; final String userId; UploadAvatarRequest({required this.file, required this.userId}); @override String get method => 'POST'; @override String resolveEndpoint() => '/users/$userId/avatar'; @override Future multipartBody() async => FormData.fromMap({ 'avatar': await MultipartFile.fromFile(file.path, filename: 'avatar.jpg'), }); } ``` -------------------------------- ### Manually Handling Status Codes by Disabling ThrowOnError Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Disable automatic exception throwing by setting throwOnError to false in a custom Connector. This allows manual checking of response success and status codes. ```dart class MyConnector extends Connector { @override bool get throwOnError => false; } final r = await connector.send(SomeRequest()); if (r.isSuccessful) { // ... } else if (r.statusCode == 404) { // ... } ``` -------------------------------- ### Disable Authentication Per Request Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Override the `useAuth` property on a `Request` to `false` to skip authentication for specific requests. ```dart class LoginRequest extends Request with HasFormBody { @override String get method => 'POST'; @override String resolveEndpoint() => '/login'; @override bool? get useAuth => false; // skip auth for this endpoint @override Map formBody() => {'email': email, 'password': password}; } ``` -------------------------------- ### Suppressing Logging for Specific Requests Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Control logging for individual requests by overriding logRequest and logResponse flags in a Request subclass. This is useful for sensitive data like credentials. ```dart class LoginRequest extends Request with HasFormBody { @override bool get logRequest => false; // don't log the request body @override bool get logResponse => false; // don't log the response token // ... } ``` -------------------------------- ### Adding Custom Interceptors to Connector Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Attach custom Dio Interceptors to a Lucky connector by overriding the interceptors getter. This allows for extending connector functionality with custom logic. ```dart class MyConnector extends Connector { @override List get interceptors => [ MyRetryInterceptor(), MyCacheInterceptor(), ]; } ``` -------------------------------- ### ConcurrencyThrottlePolicy for In-Flight Requests Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Limit the number of requests in flight simultaneously using ConcurrencyThrottlePolicy. This is useful for APIs that throttle on concurrency or to cap parallel calls. ```dart class MyConnector extends Connector { final _throttle = ConcurrencyThrottlePolicy(maxConcurrent: 3); @override ThrottlePolicy? get throttlePolicy => _throttle; } ``` -------------------------------- ### Form URL-encoded Request Body Mixin Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Defines a LoginRequest using the HasFormBody mixin for sending form URL-encoded data. Sets Content-Type to application/x-www-form-urlencoded. ```dart class LoginRequest extends Request with HasFormBody { final String email; final String password; LoginRequest(this.email, this.password); @override String get method => 'POST'; @override String resolveEndpoint() => '/login'; @override bool? get useAuth => false; // skip auth on login @override bool get logRequest => false; // don't log credentials @override Map formBody() => {'email': email, 'password': password}; } ``` -------------------------------- ### Handling Parse Errors with LuckyParseException Source: https://github.com/owlnext-fr/lucky/blob/main/README.md Catch LuckyParseException when parsing helpers like json(), jsonList(), text(), or bytes() fail due to an unexpected response body type. This is a client-side error. ```dart try { final user = response.json(); } on LuckyParseException catch (e) { print(e.message); // "Expected Map, got String" print(e.cause); // the original TypeError } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.