Adding http services along with provider + model modifications

This commit is contained in:
Ashita Prasad
2023-03-05 12:13:22 +05:30
parent 5c4ec360aa
commit aa1567851c
5 changed files with 243 additions and 9 deletions

View File

@ -1,4 +1,8 @@
import 'dart:io';
import 'dart:convert';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:http/http.dart';
import 'kvrow_model.dart'; import 'kvrow_model.dart';
import '../consts.dart'; import '../consts.dart';
@ -13,6 +17,9 @@ class RequestModel {
this.requestParams, this.requestParams,
this.requestBodyContentType = DEFAULT_BODY_CONTENT_TYPE, this.requestBodyContentType = DEFAULT_BODY_CONTENT_TYPE,
this.requestBody, this.requestBody,
this.responseStatus,
this.message,
this.responseModel,
}); });
final String id; final String id;
@ -23,6 +30,9 @@ class RequestModel {
final List<KVRow>? requestParams; final List<KVRow>? requestParams;
final ContentType requestBodyContentType; final ContentType requestBodyContentType;
final dynamic requestBody; final dynamic requestBody;
final int? responseStatus;
final String? message;
final ResponseModel? responseModel;
RequestModel duplicate({ RequestModel duplicate({
required String id, required String id,
@ -47,6 +57,9 @@ class RequestModel {
List<KVRow>? requestParams, List<KVRow>? requestParams,
ContentType? requestBodyContentType, ContentType? requestBodyContentType,
dynamic requestBody, dynamic requestBody,
int? responseStatus,
String? message,
ResponseModel? responseModel,
}) { }) {
return RequestModel( return RequestModel(
id: id ?? this.id, id: id ?? this.id,
@ -58,6 +71,9 @@ class RequestModel {
requestBodyContentType: requestBodyContentType:
requestBodyContentType ?? this.requestBodyContentType, requestBodyContentType ?? this.requestBodyContentType,
requestBody: requestBody ?? this.requestBody, requestBody: requestBody ?? this.requestBody,
responseStatus: responseStatus ?? this.responseStatus,
message: message ?? this.message,
responseModel: responseModel ?? this.responseModel,
); );
} }
@ -72,6 +88,59 @@ class RequestModel {
"Request Params: ${requestParams.toString()}", "Request Params: ${requestParams.toString()}",
"Request Body Content Type: ${requestBodyContentType.toString()}", "Request Body Content Type: ${requestBodyContentType.toString()}",
"Request Body: ${requestBody.toString()}", "Request Body: ${requestBody.toString()}",
"Response Status: $responseStatus",
"Response Message: $message",
"Response: ${responseModel.toString()}"
].join("\n");
}
}
@immutable
class ResponseModel {
const ResponseModel({
this.statusCode,
this.headers,
this.requestHeaders,
this.contentType,
this.body,
this.time,
});
final int? statusCode;
final Map<String, String>? headers;
final Map<String, String>? requestHeaders;
final String? contentType;
final String? body;
final Duration? time;
ResponseModel fromResponse({
required Response response,
Duration? time,
}) {
var contentType = response.headers[HttpHeaders.contentTypeHeader];
final responseHeaders = mergeMaps(
{HttpHeaders.contentLengthHeader: response.contentLength.toString()},
response.headers);
return ResponseModel(
statusCode: response.statusCode,
headers: responseHeaders,
requestHeaders: response.request?.headers,
contentType: contentType,
body: contentType == JSON_MIMETYPE
? utf8.decode(response.bodyBytes)
: response.body,
time: time,
);
}
@override
String toString() {
return [
"Response Status: $statusCode",
"Response Time: $time",
"Response Headers: ${headers.toString()}",
"Response Request Headers: ${requestHeaders.toString()}",
"Response Body: $body",
].join("\n"); ].join("\n");
} }
} }

View File

@ -1,6 +1,7 @@
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:uuid/uuid.dart'; import 'package:uuid/uuid.dart';
import '../models/models.dart'; import '../models/models.dart';
import '../services/services.dart';
import '../consts.dart'; import '../consts.dart';
const _uuid = Uuid(); const _uuid = Uuid();
@ -63,20 +64,51 @@ class CollectionStateNotifier extends StateNotifier<List<RequestModel>> {
List<KVRow>? requestParams, List<KVRow>? requestParams,
ContentType? requestBodyContentType, ContentType? requestBodyContentType,
dynamic requestBody, dynamic requestBody,
int? responseStatus,
String? message,
ResponseModel? responseModel,
}) { }) {
final idx = idxOfId(id); final idx = idxOfId(id);
final newModel = state[idx].copyWith( final newModel = state[idx].copyWith(
method: method, method: method,
url: url, url: url,
requestTabIndex: requestTabIndex, requestTabIndex: requestTabIndex,
requestHeaders: requestHeaders, requestHeaders: requestHeaders,
requestParams: requestParams, requestParams: requestParams,
requestBodyContentType: requestBodyContentType, requestBodyContentType: requestBodyContentType,
requestBody: requestBody, requestBody: requestBody,
); responseStatus: responseStatus,
message: message,
responseModel: responseModel);
//print(newModel); //print(newModel);
state = [...state.sublist(0, idx), newModel, ...state.sublist(idx + 1)]; state = [...state.sublist(0, idx), newModel, ...state.sublist(idx + 1)];
} }
Future<void> sendRequest(String id) async {} Future<void> sendRequest(String id) async {
final idx = idxOfId(id);
RequestModel requestModel = getRequestModel(id);
var responseRec = await request(requestModel);
late final RequestModel newRequestModel;
if (responseRec.$0 == null) {
newRequestModel = requestModel.copyWith(
responseStatus: -1,
message: responseRec.$2,
);
} else {
final responseModel = ResponseModel()
.fromResponse(response: responseRec.$0!, time: responseRec.$1!);
int statusCode = responseRec.$0!.statusCode;
newRequestModel = requestModel.copyWith(
responseStatus: statusCode,
message: RESPONSE_CODE_REASONS[statusCode],
responseModel: responseModel,
);
}
print(newRequestModel);
state = [
...state.sublist(0, idx),
newRequestModel,
...state.sublist(idx + 1)
];
}
} }

View File

@ -0,0 +1,130 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:flutter_api_tool/consts.dart';
import 'package:http/http.dart' as http;
import 'package:collection/collection.dart' show mergeMaps;
import '../models/models.dart';
const SUPPORTED_URI_SCHEMES = [
"https",
"http"
];
const DEFAULT_URI_SCHEME = "https://";
const METHODS_WITH_BODY = [HTTPVerb.post, HTTPVerb.put, HTTPVerb.patch, HTTPVerb.delete,];
(String?, bool) getUriScheme(Uri uri) {
if(uri.hasScheme){
if(SUPPORTED_URI_SCHEMES.contains(uri.scheme)){
return (uri.scheme, true);
}
return (uri.scheme, false);
}
return (null, false);
}
(Uri?, String?) getValidRequestUri(String? url, List<KVRow>? requestParams) {
if(url == null || url.trim() == ""){
return (null, "URL is missing!");
}
Uri? uri = Uri.tryParse(url);
if(uri == null){
return (null, "Check URL (malformed)");
}
(String?, bool) urlScheme = getUriScheme(uri);
if(urlScheme.$0 != null){
if (!urlScheme.$1){
return (null, "Unsupported URL Scheme (${urlScheme.$0})");
}
}
else {
url = DEFAULT_URI_SCHEME + url;
}
uri = Uri.parse(url);
if (uri.hasFragment){
uri = uri.removeFragment();
}
Map<String, String>? queryParams = rowsToMap(requestParams);
if(queryParams != null){
if(uri.hasQuery){
Map<String, String> urlQueryParams = uri.queryParameters;
queryParams = mergeMaps(urlQueryParams, queryParams);
}
uri = uri.replace(queryParameters: queryParams);
}
return (uri, null);
}
Future<(http.Response?, Duration?, String?)> request(RequestModel requestModel) async {
(Uri?, String?) uriRec = getValidRequestUri(requestModel.url,
requestModel.requestParams);
if(uriRec.$0 != null){
Uri requestUrl = uriRec.$0!;
Map<String, String> headers = rowsToMap(requestModel.requestHeaders) ?? {};
http.Response response;
String? body;
try {
if(METHODS_WITH_BODY.contains(requestModel.method)){
if(requestModel.requestBody != null){
var contentLength = utf8.encode(requestModel.requestBody).length;
if (contentLength > 0){
body = requestModel.requestBody as String;
headers[HttpHeaders.contentLengthHeader] = contentLength.toString();
switch(requestModel.requestBodyContentType){
case ContentType.json:
headers[HttpHeaders.contentTypeHeader] = 'application/json';
break;
case ContentType.text:
headers[HttpHeaders.contentTypeHeader] = 'text/plain';
break;
}
}
}
}
Stopwatch stopwatch = Stopwatch()..start();
switch(requestModel.method){
case HTTPVerb.get:
response = await http.get(requestUrl,
headers: headers);
break;
case HTTPVerb.head:
response = await http.head(requestUrl,
headers: headers);
break;
case HTTPVerb.post:
response = await http.post(requestUrl,
headers: headers,
body: body);
break;
case HTTPVerb.put:
response = await http.put(requestUrl,
headers: headers,
body: body);
break;
case HTTPVerb.patch:
response = await http.patch(requestUrl,
headers: headers,
body: body);
break;
case HTTPVerb.delete:
response = await http.delete(requestUrl,
headers: headers,
body: body);
break;
}
stopwatch.stop();
return (response, stopwatch.elapsed, null);
}
catch (e) {
return (null, null, e.toString());
}
}
else {
return (null, null, uriRec.$1);
}
}

View File

@ -0,0 +1 @@
export 'http_service.dart';

View File

@ -15,6 +15,8 @@ dependencies:
uuid: ^3.0.7 uuid: ^3.0.7
tab_container: ^2.0.0 tab_container: ^2.0.0
davi: ^3.2.0 davi: ^3.2.0
http: ^0.13.5
collection: ^1.17.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: