/// Don't use this class directly
///
/// Use the `Api` layer to call requests
class NetworkService {
static NetworkService _instance;
static NetworkService instance = _instance ??= NetworkService();
final Dio _dio = Dio();
// TODO(wouter): Inject the logger
final Logger _logger = Logger();
Observable<EIHttpResponse> request({
@required EIHttpRequest request,
CancelToken cancelToken,
ProgressCallback onReceiveProgress,
}) {
_setupDio(request);
return Observable<EIHttpResponse>(_createResponseStream(
request: request,
cancelToken: cancelToken,
onReceiveProgress: onReceiveProgress));
}
/// Private functions
Stream<EIHttpResponse> _createResponseStream({
@required EIHttpRequest request,
CancelToken cancelToken,
ProgressCallback onReceiveProgress,
}) async* {
Future<Response> response;
// Check for queryparameters
final Map<String, dynamic> queryParameters = request.queryParameters != null
? request.queryParameters.toJson()
: <String, dynamic>{};
final String _endPoint = request.endpoint;
switch (request.httpMethod) {
case HttpMethod.get:
response = _dio
.get<Map<String, dynamic>>(
_endPoint,
queryParameters: queryParameters,
cancelToken: cancelToken,
onReceiveProgress: onReceiveProgress,
)
.catchError((Object e, StackTrace stackTrace) {
_catchError(e, stackTrace);
});
break;
case HttpMethod.post:
response = _dio
.post<Map<String, dynamic>>(
_endPoint,
data: request.objectJson,
queryParameters: queryParameters,
cancelToken: cancelToken,
onReceiveProgress: onReceiveProgress,
)
.catchError((Object e, StackTrace stackTrace) {
_catchError(e, stackTrace);
});
break;
case HttpMethod.update:
response = _dio
.put<Map<String, dynamic>>(
_endPoint,
data: request.objectJson,
queryParameters: queryParameters,
cancelToken: cancelToken,
onReceiveProgress: onReceiveProgress,
)
.catchError((Object e, StackTrace stackTrace) {
_catchError(e, stackTrace);
});
break;
case HttpMethod.delete:
response = _dio
.delete<Map<String, dynamic>>(
_endPoint,
data: request.objectJson,
queryParameters: queryParameters,
cancelToken: cancelToken,
)
.catchError((Object e, StackTrace stackTrace) {
_catchError(e, stackTrace);
});
break;
}
final Future<EIHttpResponse> eiResponse = _convertResponse(response);
_logResponse(eiResponse);
yield await eiResponse;
}
void _setupDio(EIHttpRequest request) {
_dio.options.baseUrl = request.baseUrl;
_dio.options.headers = request.headers;
_dio.options.contentType = request.contentType ??= ContentType.json;
_dio.options.connectTimeout = 30000; // 30 second timeout
_dio.options.receiveTimeout = 30000; // 30 second timeout
}
Future<EIHttpResponse> _convertResponse(Future<Response> response) async {
return EIHttpResponse(await response);
}
void _catchError(Object e, StackTrace stackTrace) {
_logger.logError(error: e, logRemotely: false);
// TODO(wouter): Error handling here
if (e is SocketException) {
print('e is SocketException');
} else if (e is DioError) {
print(e.error);
throw e;
}
}
void _logResponse(Future<EIHttpResponse> response) {
response.then((EIHttpResponse response) {
_logger.logResponse(response: response);
}).catchError((Object e, StackTrace stackTrace) {
_logger.logError(error: e, logRemotely: false);
});
}
}