Line data Source code
1 : import 'package:flutter/foundation.dart';
2 : import '../worker.dart';
3 :
4 : export 'request_signing.dart';
5 :
6 : /// HTTP request worker configuration.
7 : @immutable
8 : final class HttpRequestWorker extends Worker {
9 16 : const HttpRequestWorker({
10 : required this.url,
11 : this.method = HttpMethod.get,
12 : this.headers = const {},
13 : this.body,
14 : this.timeout = const Duration(seconds: 30),
15 : this.requestSigning,
16 : this.tokenRefresh,
17 : });
18 :
19 : final String url;
20 : final HttpMethod method;
21 : final Map<String, String> headers;
22 : final String? body;
23 :
24 : /// Request timeout per attempt (default: 30 seconds).
25 : ///
26 : /// NET-027: This is a **per-attempt** timeout. WorkManager may retry the task
27 : /// after failure; each retry resets the clock.
28 : final Duration timeout;
29 :
30 : /// HMAC-SHA256 request signing configuration.
31 : ///
32 : /// When set, each request is signed with the specified secret key and the
33 : /// signature is injected as a request header (default: `X-Signature`).
34 : final RequestSigning? requestSigning;
35 :
36 : /// Automatic token refresh configuration.
37 : final TokenRefreshConfig? tokenRefresh;
38 :
39 : // ═══════════════════════════════════════════════════════════════════════════
40 : // BUILDER-STYLE copyWith + convenience methods
41 : // ═══════════════════════════════════════════════════════════════════════════
42 :
43 : /// Returns a copy with the given fields replaced.
44 2 : HttpRequestWorker copyWith({
45 : String? url,
46 : HttpMethod? method,
47 : Map<String, String>? headers,
48 : String? body,
49 : Duration? timeout,
50 : RequestSigning? requestSigning,
51 : TokenRefreshConfig? tokenRefresh,
52 : }) =>
53 2 : HttpRequestWorker(
54 2 : url: url ?? this.url,
55 2 : method: method ?? this.method,
56 1 : headers: headers ?? this.headers,
57 1 : body: body ?? this.body,
58 2 : timeout: timeout ?? this.timeout,
59 2 : requestSigning: requestSigning ?? this.requestSigning,
60 2 : tokenRefresh: tokenRefresh ?? this.tokenRefresh,
61 : );
62 :
63 : /// Convenience: add or merge HTTP headers.
64 1 : HttpRequestWorker withHeaders(Map<String, String> extra) =>
65 4 : copyWith(headers: {...headers, ...extra});
66 :
67 : /// Convenience: add `Authorization` header.
68 1 : HttpRequestWorker withAuth({
69 : required String token,
70 : String template = 'Bearer {accessToken}',
71 : }) =>
72 2 : withHeaders({
73 1 : 'Authorization': template.replaceAll('{accessToken}', token),
74 : });
75 :
76 : /// Convenience: set a JSON body (also sets `Content-Type: application/json`
77 : /// if not already present).
78 4 : HttpRequestWorker withBody(String jsonBody) => copyWith(
79 : body: jsonBody,
80 2 : headers: {
81 2 : 'Content-Type': 'application/json',
82 2 : ...headers,
83 : },
84 : );
85 :
86 : /// Convenience: sign requests with HMAC-SHA256.
87 1 : HttpRequestWorker withSigning(RequestSigning signing) =>
88 1 : copyWith(requestSigning: signing);
89 :
90 : /// Convenience: configure automatic token refresh.
91 1 : HttpRequestWorker withTokenRefresh(TokenRefreshConfig config) =>
92 1 : copyWith(tokenRefresh: config);
93 :
94 8 : @override
95 : String get workerClassName => 'HttpRequestWorker';
96 :
97 13 : @override
98 13 : Map<String, dynamic> toMap() => {
99 13 : 'workerType': 'httpRequest',
100 26 : 'url': url,
101 39 : 'method': method.name,
102 26 : 'headers': headers,
103 26 : 'body': body,
104 39 : 'timeoutMs': timeout.inMilliseconds,
105 13 : if (requestSigning != null) 'requestSigning': requestSigning!.toMap(),
106 13 : if (tokenRefresh != null) 'tokenRefresh': tokenRefresh!.toMap(),
107 : };
108 : }
|