Skip to content

Instantly share code, notes, and snippets.

@kabirnayeem99
Forked from dev4jam/network_service.dart
Created October 21, 2022 06:29
Show Gist options
  • Save kabirnayeem99/c4ec7c5de8f77fe0d83fd8c16afa538f to your computer and use it in GitHub Desktop.
Save kabirnayeem99/c4ec7c5de8f77fe0d83fd8c16afa538f to your computer and use it in GitHub Desktop.
Full source code of the Network Service
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:io';
part 'NetworkRequestBody.freezed.dart';
part 'NetworkResponse.freezed.dart';
class AccessTokenResponse {
String? accessToken;
AccessTokenResponse.fromJson(Map<String, dynamic> json) {
accessToken = json['access_token'];
}
}
@freezed
class NetworkRequestBody with _$NetworkRequestBody {
const factory NetworkRequestBody.empty() = Empty;
const factory NetworkRequestBody.json(Map<String, dynamic> data) = Json;
const factory NetworkRequestBody.text(String data) = Text;
}
enum NetworkRequestType { GET, POST, PUT, PATCH, DELETE }
class NetworkRequest {
const NetworkRequest({
required this.type,
required this.path,
required this.data,
this.queryParams,
this.headers,
});
final NetworkRequestType type;
final String path;
final NetworkRequestBody data;
final Map<String, dynamic>? queryParams;
final Map<String, String>? headers;
}
@freezed
class NetworkResponse<Model> with _$NetworkResponse {
const factory NetworkResponse.ok(Model data) = Ok;
const factory NetworkResponse.invalidParameters(String message) = InvalidParameters;
const factory NetworkResponse.noAuth(String message) = NoAuth; //401
const factory NetworkResponse.noAccess(String message) = NoAccess; //403
const factory NetworkResponse.badRequest(String message) = BadRequest; //400
const factory NetworkResponse.notFound(String message) = NotFound; //404
const factory NetworkResponse.conflict(String message) = Conflict; //409
const factory NetworkResponse.noData(String message) = NoData; //500
}
class _PreparedNetworkRequest<Model> {
const _PreparedNetworkRequest(
this.request,
this.parser,
this.dio,
this.headers,
this.onSendProgress,
this.onReceiveProgress,
);
final NetworkRequest request;
final Model Function(Map<String, dynamic>) parser;
final Dio dio;
final Map<String, dynamic> headers;
final ProgressCallback? onSendProgress;
final ProgressCallback? onReceiveProgress;
}
Future<NetworkResponse<Model>> executeRequest<Model>(
_PreparedNetworkRequest request,
) async {
try {
dynamic body = request.request.data.whenOrNull(
json: (data) => data,
text: (data) => data,
);
final response = await request.dio.request(
request.request.path,
data: body,
queryParameters: request.request.queryParams,
options: Dio.Options(
method: request.request.type.name,
headers: request.headers,
),
onSendProgress: request.onSendProgress,
onReceiveProgress: request.onReceiveProgress,
);
return NetworkResponse.ok(request.parser(response.data));
} on Dio.DioError catch (error) {
final errorText = error.toString();
if (error.requestOptions.cancelToken!.isCancelled) {
return NetworkResponse.noData(errorText);
}
switch (error.response?.statusCode) {
case 400:
return NetworkResponse.badRequest(errorText);
case 401:
return NetworkResponse.noAuth(errorText);
case 403:
return NetworkResponse.noAccess(errorText);
case 404:
return NetworkResponse.notFound(errorText);
case 409:
return NetworkResponse.conflict(errorText);
default:
return NetworkResponse.noData(errorText);
}
} catch (error) {
return NetworkResponse.noData(error.toString());
}
}
class NetworkService {
NetworkService({
required this.baseUrl,
dioClient,
httpHeaders,
}) : this._dio = dioClient,
this._headers = httpHeaders ?? {};
Dio? _dio;
final String baseUrl;
Map<String, String> _headers;
Future<Dio> _getDefaultDioClient() async {
_headers['content-type'] = 'application/json; charset=utf-8';
final dio = Dio()
..options.baseUrl = baseUrl
..options.headers = _headers
..options.connectTimeout = 5000 // 5 seconds
..options.receiveTimeout = 3000; // 3 seconds
}
return dio;
}
void addBasicAuth(String accessToken) {
_headers['Authorization'] = 'Bearer $accessToken';
}
Future<NetworkResponse<Model>> execute<Model>(
NetworkRequest request,
Model Function(Map<String, dynamic>) parser, {
ProgressCallback? onSendProgress = null,
ProgressCallback? onReceiveProgress = null,
}) async {
if (_dio == null) {
_dio = await _getDefaultDioClient();
}
final req = _PreparedNetworkRequest<Model>(
request,
parser,
_dio!,
{..._headers, ...(request.headers ?? {})},
onSendProgress,
onReceiveProgress,
);
final result = await compute(
executeRequest<Model>,
req,
);
return result;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment