Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create package ew_http for HTTP REQUEST #1175

Merged
merged 10 commits into from
Apr 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions packages/ew_http/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Ew Http

Encointer HTTP REQUEST

* ew_http with [http](https://pub.dev/packages/http)

## Example
```dart
const getListUrl = 'https://encointer.github.io/feed/community_messages/en/cm.json';
const getUrl = 'https://eldar2021.github.io/encointer/test_data.json';

final ewHttp = EwHttp();

final mapValue = await ewHttp.get<Map<String, dynamic>>(getUrl);
print(mapValue);
// {
// "id": "msg-1",
// "title": "App notifications are now activated",
// "content": "From now on you will receive app notifications from your community",
// "showAt": "2022-08-25T12:30:00.00+00:00"
// }

final testModel = await ewHttp.getType<TestModel>(getUrl, fromJson: TestModel.fromJson);
print(testModel); // Instance of 'TestModel'

final testModelList = await ewHttp.getType<TestModel>(getUrl, fromJson: TestModel.fromJson);
print(testModelList); // [Instance of 'TestModel', ..., Instance of 'TestModel']
```
8 changes: 8 additions & 0 deletions packages/ew_http/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
include: package:very_good_analysis/analysis_options.4.0.0.yaml

linter:
rules:
public_member_api_docs: false
lines_longer_than_80_chars: false
sort_pub_dependencies: false
directives_ordering: false
7 changes: 7 additions & 0 deletions packages/ew_http/lib/ew_http.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/// Ew Http Dart package
library ew_http;

export 'package:http/http.dart';

export 'src/exceptions/exceptions.dart';
export 'src/ew_http.dart';
68 changes: 68 additions & 0 deletions packages/ew_http/lib/src/ew_http.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import 'dart:convert';
import 'dart:io';

import 'package:http/http.dart' as http;

import 'package:ew_http/src/exceptions/exceptions.dart';

typedef TokenProvider = Future<String?> Function();
typedef FromJson<T> = T Function(Map<String, dynamic>);

class EwHttp {
EwHttp({http.Client? client, TokenProvider? tokenProvider})
: _client = client ?? http.Client(),
_tokenProvider = tokenProvider;

final http.Client _client;
final TokenProvider? _tokenProvider;

Future<T> get<T>(String url) async {
try {
final uri = Uri.parse(url);
final response = await _client.get(uri, headers: await _getRequestHeaders());
if (response.statusCode != HttpStatus.ok) {
throw HttpRequestException(statusCode: response.statusCode);
}
return response.decode<T>();
} catch (e, s) {
throw HttpRequestException(error: e, stackTrace: s);
}
}

Future<T> getType<T>(String url, {required FromJson<T> fromJson}) async {
try {
final data = await get<Map<String, dynamic>>(url);
return fromJson(data);
} catch (e, s) {
throw JsonDeserializationException(error: e, stackTrace: s);
}
}

Future<List<T>> getTypeList<T>(String url, {required FromJson<T> fromJson}) async {
try {
final data = await get<List<dynamic>>(url);
return data.map((e) => fromJson(e as Map<String, dynamic>)).toList();
} catch (e, s) {
throw JsonDeserializationException(error: e, stackTrace: s);
}
}

Future<Map<String, String>> _getRequestHeaders() async {
final token = _tokenProvider != null ? await _tokenProvider!() : null;
return <String, String>{
HttpHeaders.contentTypeHeader: ContentType.json.value,
HttpHeaders.acceptHeader: ContentType.json.value,
if (token != null) HttpHeaders.authorizationHeader: 'Bearer $token',
};
}
}

extension on http.Response {
T decode<T>() {
try {
return jsonDecode(body) as T;
} catch (e, s) {
throw JsonDecodeException(error: e, stackTrace: s);
}
}
}
21 changes: 21 additions & 0 deletions packages/ew_http/lib/src/exceptions/exceptions.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
class HttpRequestException implements Exception {
const HttpRequestException({this.error, this.stackTrace, this.statusCode});

final dynamic error;
final StackTrace? stackTrace;
final int? statusCode;
}

class JsonDecodeException implements Exception {
const JsonDecodeException({this.error, this.stackTrace});

final dynamic error;
final StackTrace? stackTrace;
}

class JsonDeserializationException implements Exception {
const JsonDeserializationException({this.error, this.stackTrace});

final dynamic error;
final StackTrace? stackTrace;
}
15 changes: 15 additions & 0 deletions packages/ew_http/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: ew_http
description: Ew Http Dart package
version: 0.1.0+1
publish_to: none

environment:
sdk: ">=2.18.0 <3.0.0"

dependencies:
http: ^0.13.5

dev_dependencies:
mocktail: ^0.3.0
test: 1.22.0
very_good_analysis: ^4.0.0
43 changes: 43 additions & 0 deletions packages/ew_http/test/ew_http_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import 'package:test/test.dart';

import 'package:ew_http/ew_http.dart';

import 'test_model.dart';

void main() {
late EwHttp ewHttp;

const getListUrl = 'https://encointer.github.io/feed/community_messages/en/cm.json';
const getUrl = 'https://eldar2021.github.io/encointer/test_data.json';

setUp(() {
ewHttp = EwHttp();
});

group('EwHttp `get`, `getType`, `getListType`', () {
test('Get', () async {
final mapValue = await ewHttp.get<Map<String, dynamic>>(getUrl);
expect(mapValue, isNotNull);
expect(mapValue, isMap);
expect(mapValue, isA<Map<String, dynamic>>());

final listValue = await ewHttp.get<List<dynamic>>(getListUrl);
expect(listValue, isNotNull);
expect(listValue, isList);
expect(listValue, isA<List<dynamic>>());
});

test('Get Type', () async {
final value = await ewHttp.getType<TestModel>(getUrl, fromJson: TestModel.fromJson);
expect(value, isNotNull);
expect(value, isA<TestModel>());
});

test('Get List Type', () async {
final value = await ewHttp.getTypeList<TestModel>(getListUrl, fromJson: TestModel.fromJson);
expect(value, isNotNull);
expect(value, isList);
expect(value[0], isA<TestModel>());
});
});
}
31 changes: 31 additions & 0 deletions packages/ew_http/test/test_model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
class TestModel {
const TestModel({
required this.id,
required this.title,
required this.content,
required this.showAt,
});

factory TestModel.fromJson(Map<String, dynamic> json) {
return TestModel(
id: json['id'] as String,
title: json['title'] as String,
content: json['content'] as String,
showAt: json['showAt'] as String,
);
}

final String id;
final String title;
final String content;
final String showAt;

Map<String, dynamic> toJson() {
return <String, dynamic>{
'id': id,
'title': title,
'content': content,
'showAt': showAt,
};
}
}