Line data Source code
1 : import 'package:dio/dio.dart';
2 : import 'package:meta/meta.dart';
3 :
4 : import 'package:stream_feed_dart/src/core/exceptions.dart';
5 : import 'package:stream_feed_dart/src/core/util/extension.dart';
6 : import 'package:stream_feed_dart/version.dart';
7 : import 'package:stream_feed_dart/src/core/platform_detector/platform_detector.dart';
8 : import 'package:stream_feed_dart/src/core/location.dart';
9 :
10 : part 'stream_http_client_options.dart';
11 :
12 : ///
13 : class StreamHttpClient {
14 : ///
15 1 : StreamHttpClient(
16 : this.apiKey, {
17 : StreamHttpClientOptions? options,
18 : }) : options = options ?? const StreamHttpClientOptions(),
19 1 : httpClient = Dio() {
20 1 : httpClient
21 5 : ..options.receiveTimeout = this.options.receiveTimeout.inMilliseconds
22 5 : ..options.connectTimeout = this.options.connectTimeout.inMilliseconds
23 3 : ..options.queryParameters = {
24 1 : 'api_key': apiKey,
25 2 : 'location': this.options.group,
26 : }
27 3 : ..options.headers = {
28 : 'stream-auth-type': 'jwt',
29 2 : 'x-stream-client': this.options._userAgent,
30 : }
31 3 : ..interceptors.add(LogInterceptor(
32 : requestBody: true,
33 : responseBody: true,
34 : ));
35 : }
36 :
37 : /// Your project Stream Chat api key.
38 : /// Find your API keys here https://getstream.io/dashboard/
39 : final String apiKey;
40 :
41 : /// Your project Stream Feed clientOptions.
42 : final StreamHttpClientOptions options;
43 :
44 : /// [Dio] httpClient
45 : /// It's been chosen because it's easy to use
46 : /// and supports interesting features out of the box
47 : /// (Interceptors, Global configuration, FormData, File downloading etc.)
48 : @visibleForTesting
49 : final Dio httpClient;
50 :
51 0 : Exception _parseError(DioError error) {
52 0 : if (error.type == DioErrorType.response) {
53 0 : final apiError = StreamApiException(
54 0 : error.response?.data?.toString(), error.response?.statusCode);
55 : return apiError;
56 : }
57 : return error;
58 : }
59 :
60 : /// Combines the base url with the [relativeUrl]
61 1 : String enrichUrl(String relativeUrl, String serviceName) =>
62 3 : '${options._getBaseUrl(serviceName)}/$relativeUrl';
63 :
64 : /// Handy method to make http GET request with error parsing.
65 0 : Future<Response<T>> get<T>(
66 : String path, {
67 : String serviceName = 'api',
68 : Map<String, Object?>? queryParameters,
69 : Map<String, Object?>? headers,
70 : }) async {
71 : try {
72 0 : final response = await httpClient.get<T>(
73 0 : enrichUrl(path, serviceName),
74 0 : queryParameters: queryParameters?.nullProtected,
75 0 : options: Options(headers: headers?.nullProtected),
76 : );
77 : return response;
78 0 : } on DioError catch (error) {
79 0 : throw _parseError(error);
80 : }
81 : }
82 :
83 : /// Handy method to make http POST request with error parsing.
84 0 : Future<Response<T>> post<T>(
85 : String path, {
86 : String serviceName = 'api',
87 : Object? data,
88 : Map<String, Object?>? queryParameters,
89 : Map<String, Object?>? headers,
90 : }) async {
91 : try {
92 0 : final response = await httpClient.post<T>(
93 0 : enrichUrl(path, serviceName),
94 0 : queryParameters: queryParameters?.nullProtected,
95 : data: data,
96 0 : options: Options(headers: headers?.nullProtected),
97 : );
98 : return response;
99 0 : } on DioError catch (error) {
100 0 : throw _parseError(error);
101 : }
102 : }
103 :
104 : /// Handy method to make http DELETE request with error parsing.
105 0 : Future<Response<T>> delete<T>(
106 : String path, {
107 : String serviceName = 'api',
108 : Map<String, Object?>? queryParameters,
109 : Map<String, Object?>? headers,
110 : }) async {
111 : try {
112 0 : final response = await httpClient.delete<T>(
113 0 : enrichUrl(path, serviceName),
114 0 : queryParameters: queryParameters?.nullProtected,
115 0 : options: Options(headers: headers?.nullProtected),
116 : );
117 : return response;
118 0 : } on DioError catch (error) {
119 0 : throw _parseError(error);
120 : }
121 : }
122 :
123 : /// Handy method to make http PATCH request with error parsing.
124 0 : Future<Response<T>> patch<T>(
125 : String path, {
126 : String serviceName = 'api',
127 : Object? data,
128 : Map<String, Object?>? queryParameters,
129 : Map<String, Object?>? headers,
130 : }) async {
131 : try {
132 0 : final response = await httpClient.patch<T>(
133 0 : enrichUrl(path, serviceName),
134 0 : queryParameters: queryParameters?.nullProtected,
135 : data: data,
136 0 : options: Options(headers: headers?.nullProtected),
137 : );
138 : return response;
139 0 : } on DioError catch (error) {
140 0 : throw _parseError(error);
141 : }
142 : }
143 :
144 : /// Handy method to make http PUT request with error parsing.
145 0 : Future<Response<T>> put<T>(
146 : String path, {
147 : String serviceName = 'api',
148 : Object? data,
149 : Map<String, Object?>? queryParameters,
150 : Map<String, Object?>? headers,
151 : }) async {
152 : try {
153 0 : final response = await httpClient.put<T>(
154 0 : enrichUrl(path, serviceName),
155 0 : queryParameters: queryParameters?.nullProtected,
156 : data: data,
157 0 : options: Options(headers: headers?.nullProtected),
158 : );
159 : return response;
160 0 : } on DioError catch (error) {
161 0 : throw _parseError(error);
162 : }
163 : }
164 :
165 : /// Handy method to post files with error parsing.
166 0 : Future<Response<T>> postFile<T>(
167 : String path,
168 : MultipartFile file, {
169 : String serviceName = 'api',
170 : Map<String, Object?>? queryParameters,
171 : Map<String, Object?>? headers,
172 : }) async {
173 : try {
174 0 : final formData = FormData.fromMap({'file': file});
175 0 : final response = await post<T>(
176 0 : enrichUrl(path, serviceName),
177 : data: formData,
178 : queryParameters: queryParameters,
179 : headers: headers,
180 : );
181 : return response;
182 0 : } on DioError catch (error) {
183 0 : throw _parseError(error);
184 : }
185 : }
186 : }
|