diff --git a/lib/src/exception/base_http_exception.dart b/lib/src/exception/base_http_exception.dart index 44bad41..940031a 100644 --- a/lib/src/exception/base_http_exception.dart +++ b/lib/src/exception/base_http_exception.dart @@ -13,9 +13,7 @@ class BaseHttpResponseException { this.responseType = ResponseType.json, }); - Response call() => Response( - responseType == ResponseType.html ? message : {'message': message}, - responseType, - code, - ); + Response response(bool isJson) => isJson + ? Response.json({'message': message}, code) + : Response.html(message); } diff --git a/lib/src/exception/not_found_exception.dart b/lib/src/exception/not_found_exception.dart index d0c416a..8618ccb 100644 --- a/lib/src/exception/not_found_exception.dart +++ b/lib/src/exception/not_found_exception.dart @@ -7,6 +7,6 @@ class NotFoundException extends BaseHttpResponseException { super.message = 'Not Fount 404', super.code = HttpStatus.notFound, super.errorCode = 'Not found 404', - super.responseType = ResponseType.json, + super.responseType = ResponseType.html, }); } diff --git a/lib/src/extensions/date_time_aws_format.dart b/lib/src/extensions/date_time_aws_format.dart index 5ee5c8f..697cd44 100644 --- a/lib/src/extensions/date_time_aws_format.dart +++ b/lib/src/extensions/date_time_aws_format.dart @@ -6,3 +6,14 @@ extension DateTimeAwsFormat on DateTime { '${zeroPad(hour)}${zeroPad(minute)}${zeroPad(second)}Z'; } } + +extension DateTimeFormatting on DateTime { + String format() { + return '${year.toString().padLeft(4, '0')}-' + '${month.toString().padLeft(2, '0')}-' + '${day.toString().padLeft(2, '0')} ' + '${hour.toString().padLeft(2, '0')}:' + '${minute.toString().padLeft(2, '0')}:' + '${second.toString().padLeft(2, '0')}'; + } +} diff --git a/lib/src/http/controller/controller_handler.dart b/lib/src/http/controller/controller_handler.dart index 28f355d..c05d162 100644 --- a/lib/src/http/controller/controller_handler.dart +++ b/lib/src/http/controller/controller_handler.dart @@ -1,90 +1,51 @@ -import 'dart:convert'; -import 'dart:io'; -import 'package:vania/src/exception/invalid_argument_exception.dart'; +import 'package:vania/src/exception/validation_exception.dart'; import 'package:vania/src/route/route_data.dart'; import 'package:vania/vania.dart'; class ControllerHandler { - final RouteData route; - final Request request; - ControllerHandler({required this.route, required this.request}) { - handler(); - } - - void handler() async { + void create({ + required RouteData route, + required Request request, + }) async { List positionalArguments = []; - Function? function; - if (route.action is Function) { - function = route.action; - } - - if (function == null) { - request.response.statusCode = HttpStatus.internalServerError; - if (request.request.headers.contentType.toString() == - "application/json") { - request.response.headers.contentType = ContentType.json; - - request.response.write(jsonEncode({'message': 'Method not found'})); - } else { - request.response.headers.contentType = ContentType.html; - request.response.write('Method not found'); - } - request.response.close(); - return; - } - - Map params = {}; - - params.addAll(route.params ?? {}); - - var argsList = extractFunctionArgs(function); - var requestArgIndex = argsList.indexOf("Request"); - - if (requestArgIndex > -1) { - argsList.removeAt(requestArgIndex); - } - - if (argsList.isNotEmpty) { - positionalArguments = params.values - .map((item) => int.tryParse(item.toString()) ?? item) + if (route.params != null) { + positionalArguments = route.params!.values + .map((param) => int.tryParse(param) ?? param) .toList(); } - if (requestArgIndex > -1) { - positionalArguments.insert(requestArgIndex, request); + if (route.hasRequest) { + positionalArguments.insert(0, request); } try { - Response data = await Function.apply(function, positionalArguments, {}); - data.makeResponse(request.response); - } on BaseHttpResponseException catch (e) { - e.call().makeResponse(request.response); - } on InvalidArgumentException catch (_) { - rethrow; - } - } - - List extractFunctionArgs(Function function) { - String functionString = function.toString(); - String paramsString = functionString.split(RegExp(r'\(|\)'))[1].trim(); - - RegExp regex = RegExp(r'(.+?)\s*\{(.+?)\}'); - Match? match = - regex.firstMatch(paramsString.replaceAll('[', '').replaceAll(']', '')); - - if (match == null) { - return removeDynamicPart(paramsString) - .replaceAll('[', '') - .replaceAll(']', '') - .split(','); - } else { - return removeDynamicPart(match.group(1).toString()).split(','); + Response response = await Function.apply( + route.action, + positionalArguments, + {}, + ); + + response.makeResponse(request.response); + } on ValidationException catch (error) { + error + .response(request.headers['accept'] == "application/json") + .makeResponse(request.response); + } catch (error) { + _response(request, error.toString()); } } } -String removeDynamicPart(String input) { - RegExp regExp = RegExp(r'\{[^\}]*\}'); - return input.replaceAll(regExp, ''); +void _response(Request req, message, [statusCode = 400]) { + if (req.headers['accept'] == "application/json") { + Response.json( + { + "message": message, + }, + statusCode, + ).makeResponse(req.response); + } else { + Response.html(message).makeResponse(req.response); + } } diff --git a/lib/src/http/request/request.dart b/lib/src/http/request/request.dart index 378eb64..aafb351 100644 --- a/lib/src/http/request/request.dart +++ b/lib/src/http/request/request.dart @@ -8,7 +8,8 @@ import 'package:vania/vania.dart'; class Request { final HttpRequest request; final RouteData? route; - Request({required this.request, this.route}); + + Request.from({required this.request, this.route}); String? get ip => request.connectionInfo?.remoteAddress.address; @@ -39,7 +40,10 @@ class Request { } Future extractBody() async { - if (request.method.toLowerCase() == 'post') { + final whereMethod = ['post', 'patch', 'put'] + .where((method) => method == request.method.toLowerCase()) + .toList(); + if (whereMethod.isNotEmpty) { body = await RequestBody.extractBody(request: request); } return this; diff --git a/lib/src/http/request/request_handler.dart b/lib/src/http/request/request_handler.dart index 47f09d9..07086c5 100644 --- a/lib/src/http/request/request_handler.dart +++ b/lib/src/http/request/request_handler.dart @@ -1,5 +1,4 @@ import 'dart:io'; - import 'package:vania/src/config/http_cors.dart'; import 'package:vania/src/exception/invalid_argument_exception.dart'; import 'package:vania/src/http/controller/controller_handler.dart'; @@ -18,11 +17,9 @@ Future httpRequestHandler(HttpRequest req) async { try { /// Check if cors is enabled HttpCors(req); - RouteData? route = httpRouteHandler(req); - - Request request = await Request(request: req, route: route).extractBody(); - + Request request = Request.from(request: req, route: route); + await request.extractBody(); if (route == null) return; /// check if pre middleware exist and call it @@ -31,15 +28,35 @@ Future httpRequestHandler(HttpRequest req) async { } /// Controller and method handler - ControllerHandler(route: route, request: request); - } on BaseHttpResponseException catch (e) { - e.call().makeResponse(req.response); + ControllerHandler().create( + route: route, + request: request, + ); + } on BaseHttpResponseException catch (error) { + error + .response( + req.headers.value('accept') == "application/json", + ) + .makeResponse(req.response); } on InvalidArgumentException catch (e) { - print(e.message); Logger.log(e.message, type: Logger.ERROR); + _response(req, e.message); } catch (e) { - print(e.toString()); Logger.log(e.toString(), type: Logger.ERROR); + _response(req, e.toString()); } } } + +void _response(req, message) { + if (req.headers.value('accept') == "application/json") { + Response.json( + { + "message": message, + }, + 400, + ).makeResponse(req.response); + } else { + Response.html(message).makeResponse(req.response); + } +} diff --git a/lib/src/redis/command/client.dart b/lib/src/redis/command/client.dart index 0b01c52..24d9131 100644 --- a/lib/src/redis/command/client.dart +++ b/lib/src/redis/command/client.dart @@ -5,7 +5,7 @@ import 'package:vania/src/redis/lowlevel/protocol_client.dart'; import 'package:vania/src/redis/lowlevel/resp.dart'; import 'package:vania/vania.dart'; -class _MultiCodec { +class MultiCodec { final List codecs = [ RedisCodec(encoder: StringEncoder(), decoder: StringDecoder()), RedisCodec(encoder: IntEncoder(), decoder: IntDecoder()), @@ -48,10 +48,10 @@ class CommandsClient implements Commands { CommandsClient._(this._connection); /// key type codecs - final _MultiCodec keyCodec = _MultiCodec(); + final MultiCodec keyCodec = MultiCodec(); /// value type codecs - final _MultiCodec valueCodec = _MultiCodec(); + final MultiCodec valueCodec = MultiCodec(); @override Future del(K key) async { diff --git a/lib/src/redis/lowlevel/resp.dart b/lib/src/redis/lowlevel/resp.dart index ea026ea..2753b3b 100644 --- a/lib/src/redis/lowlevel/resp.dart +++ b/lib/src/redis/lowlevel/resp.dart @@ -35,7 +35,7 @@ class Resp { /// serialize value implementation String _serializeValue(dynamic value, {bool isBulkString = true}) { if (value is String) { - if (!isBulkString && !value.contains(RegExp('\s'))) { + if (!isBulkString && !value.contains(RegExp('s'))) { return '+$value$_CRLF'; } return '\$${value.length}$_CRLF$value$_CRLF'; diff --git a/lib/src/route/route_data.dart b/lib/src/route/route_data.dart index d874e28..2d88450 100644 --- a/lib/src/route/route_data.dart +++ b/lib/src/route/route_data.dart @@ -3,12 +3,15 @@ import 'package:vania/vania.dart'; class RouteData { final String method; String path; - final dynamic action; + final Function action; Map? params; List preMiddleware; String? domain; final bool? corsEnabled; + final bool hasRequest; final String? prefix; + Map? paramTypes; + Map? regex; RouteData({ required this.method, @@ -19,5 +22,8 @@ class RouteData { this.preMiddleware = const [], this.domain, this.prefix, + this.hasRequest = false, + this.paramTypes, + this.regex, }); } diff --git a/lib/src/route/route_handler.dart b/lib/src/route/route_handler.dart index bee20b5..7e29d00 100644 --- a/lib/src/route/route_handler.dart +++ b/lib/src/route/route_handler.dart @@ -2,9 +2,9 @@ import 'dart:io'; import 'package:vania/src/enum/http_request_method.dart'; import 'package:vania/src/exception/not_found_exception.dart'; import 'package:vania/src/route/route_data.dart'; -import 'package:vania/src/route/router.dart'; import 'package:vania/src/route/set_static_path.dart'; import 'package:vania/src/utils/functions.dart'; +import 'package:vania/vania.dart'; RouteData? httpRouteHandler(HttpRequest req) { final route = _getMatchRoute( @@ -20,8 +20,11 @@ RouteData? httpRouteHandler(HttpRequest req) { } else { final isFile = setStaticPath(req); if (isFile == null) { - if (req.headers.contentType.toString().contains("application/json")) { - throw NotFoundException(message: {'message': 'Not found'}); + if (req.headers.value('accept') == "application/json") { + throw NotFoundException( + message: {'message': 'Not found'}, + responseType: ResponseType.json, + ); } else { throw NotFoundException(); } @@ -58,12 +61,30 @@ String? _extractDomainPlaceholder(String input) { RouteData? _getMatchRoute(String inputRoute, String method, String? domain) { String? domainParameter; String? domainPlaceholder; + List routesList = Router().routes.where((route) { + String routePath = route.path + .trim() + .replaceFirst(RegExp(r'^/'), '') + .replaceFirst(RegExp(r'/$'), ''); + inputRoute = inputRoute + .replaceFirst(RegExp(r'^/'), '') + .replaceFirst(RegExp(r'/$'), ''); + + if (route.prefix != null) { + routePath = + "${route.prefix!.replaceFirst(RegExp(r'^/'), '').replaceFirst(RegExp(r'/$'), '')}/$routePath"; + } + + if (routePath.split('/').length != inputRoute.split('/').length) { + return false; + } return route.method.toLowerCase() == method.toLowerCase() && inputRoute.contains( - route.path.replaceAll(RegExp(r'/\{[^}]*\}'), '').split('/').last, + routePath.replaceAll(RegExp(r'/\{[^}]*\}'), '').split('/').last, ); }).toList(); + RouteData? matchRoute; for (RouteData route in routesList) { if (route.domain != null && domain != null) { @@ -84,10 +105,6 @@ RouteData? _getMatchRoute(String inputRoute, String method, String? domain) { inputRoute = sanitizeRoutePath(inputRoute.toLowerCase()); String routePath = route.path.trim(); - if (route.prefix != null) { - routePath = "${route.prefix}/$routePath"; - } - /// When route is the same route exactly same route. /// route without params, eg. /api/example if (routePath == inputRoute.trim() && route.domain == null) { @@ -95,15 +112,34 @@ RouteData? _getMatchRoute(String inputRoute, String method, String? domain) { break; } + if (route.prefix != null) { + routePath = "${route.prefix}/$routePath"; + } + /// when route have params /// eg. /api/admin/{adminId} Iterable parameterNames = _getParameterNameFromRoute(route); - - Iterable matches = _getPatternMatches(inputRoute, routePath); + Iterable matches = _getPatternMatches( + inputRoute, + routePath, + ); if (matches.isNotEmpty) { + final params = _getParameterAsMap(matches, parameterNames); + if (route.paramTypes != null) { + if (!checkParamType(params, route.paramTypes!)) { + continue; + } + } + + if (route.regex != null) { + if (!checkParamWithRegex(params, route.regex!)) { + continue; + } + } + matchRoute = route; - matchRoute.params = _getParameterAsMap(matches, parameterNames); + matchRoute.params = params; if (domainPlaceholder != null && domainParameter != null) { matchRoute.params?.addAll({ domainPlaceholder: domainParameter, @@ -115,7 +151,38 @@ RouteData? _getMatchRoute(String inputRoute, String method, String? domain) { return matchRoute; } -/// get parameter name from named route eg. /blog/{id} +bool checkParamWithRegex( + Map param, Map regexPatterns) { + for (var key in regexPatterns.keys) { + var value = param[key]; + var pattern = regexPatterns[key]!; + if (value is String && !RegExp(pattern).hasMatch(value)) { + return false; + } else if (value is int && !RegExp(pattern).hasMatch(value.toString())) { + return false; + } + } + return true; +} + +bool checkParamType(Map param, Map paramType) { + bool isValidType(dynamic value, String type) { + value = int.tryParse(value.toString()) ?? value; + if (type == 'String') return value is String; + if (type == 'int') return value is int; + return false; + } + + for (var key in paramType.keys) { + if (!param.containsKey(key) || + !isValidType(param[key], paramType[key]!.toString())) { + return false; + } + } + return true; +} + +/// Get parameter name from named route eg. /blog/{id} /// eg ('id') Iterable _getParameterNameFromRoute(RouteData route) { return route.path @@ -124,7 +191,7 @@ Iterable _getParameterNameFromRoute(RouteData route) { .map((String part) => part.substring(1, part.length - 1)); } -/// get pattern matched routes from the list +/// Get pattern matched routes from the list Iterable _getPatternMatches( String input, String route, @@ -134,7 +201,7 @@ Iterable _getPatternMatches( return pattern.allMatches(input); } -/// get the param from the named route as Map response +/// Get the param from the named route as Map response /// eg {'id' : 1} Map _getParameterAsMap( Iterable matches, diff --git a/lib/src/route/router.dart b/lib/src/route/router.dart index d85d444..9c0158e 100644 --- a/lib/src/route/router.dart +++ b/lib/src/route/router.dart @@ -13,71 +13,60 @@ class Router { String? _groupDomain; List? _groupMiddleware; - static basePrefix(String prefix) { - if (prefix.endsWith("/")) { - prefix = prefix.substring(0, prefix.length - 1); - } - Router()._prefix = prefix; - } - final List _routes = []; List get routes => _routes; - static Router get(String path, dynamic action) { - return Router() - ._addRoute(HttpRequestMethod.get, path, action) - .middleware(Router()._groupMiddleware) - .domain(Router()._groupDomain) - .prefix(Router()._groupPrefix); - } - - static Router post(String path, dynamic action) { - return Router() - ._addRoute(HttpRequestMethod.post, path, action) - .middleware(Router()._groupMiddleware) - .domain(Router()._groupDomain) - .prefix(Router()._groupPrefix); + /// Sets the base prefix for all routes. + static void basePrefix(String prefix) { + Router()._prefix = + prefix.endsWith("/") ? prefix.substring(0, prefix.length - 1) : prefix; } - static Router put(String path, dynamic action) { - return Router() - ._addRoute(HttpRequestMethod.put, path, action) - .middleware(Router()._groupMiddleware) - .domain(Router()._groupDomain) - .prefix(Router()._groupPrefix); + /// Adds a route internally. + Router _addRouteInternal( + HttpRequestMethod method, + String path, + Function action, { + Map? paramTypes, + Map? regex, + }) { + bool hasRequest = _getRequestVar(action.toString()); + _routes.add(RouteData( + method: method.name, + path: path, + action: action, + prefix: _prefix, + paramTypes: paramTypes, + regex: regex, + hasRequest: hasRequest, + )); + return this; } - static Router patch(String path, dynamic action) { - return Router() - ._addRoute(HttpRequestMethod.patch, path, action) - .middleware(Router()._groupMiddleware) - .domain(Router()._groupDomain) - .prefix(Router()._groupPrefix); + bool _getRequestVar(String input) { + RegExp closureRegExp = RegExp(r'Closure: \(([^)]*)\) =>'); + Match? closureMatch = closureRegExp.firstMatch(input); + if (closureMatch == null) return false; + if (closureMatch.group(1)!.contains('Request') && + closureMatch.group(1)!.split(',')[0] == 'Request') { + return true; + } else { + return false; + } } - static Router delete(String path, dynamic action) { + /// Adds a route for the specified HTTP method, path, and action. + static Router _addRoute( + HttpRequestMethod method, String path, Function action) { return Router() - ._addRoute(HttpRequestMethod.delete, path, action) + ._addRouteInternal(method, path, action) .middleware(Router()._groupMiddleware) .domain(Router()._groupDomain) .prefix(Router()._groupPrefix); } - static Router options(String path, dynamic action) { - return Router() - ._addRoute(HttpRequestMethod.options, path, action) - .middleware(Router()._groupMiddleware) - .domain(Router()._groupDomain) - .prefix(Router()._prefix); - } - - Router _addRoute(HttpRequestMethod method, String path, dynamic action) { - _routes.add(RouteData( - method: method.name, path: path, action: action, prefix: _prefix)); - return this; - } - + /// Adds middleware to the last added route. Router middleware([List? middleware]) { if (middleware != null) { if (_routes.last.preMiddleware.isNotEmpty) { @@ -88,16 +77,17 @@ class Router { return this; } + /// Adds a prefix to the last added route. Router prefix([String? prefix]) { if (prefix != null) { String basePath = _routes.last.path; _routes.last.path = prefix.endsWith("/") ? "$prefix$basePath" : "$prefix/$basePath"; } - return this; } + /// Adds a domain to the last added route. Router domain([String? domain]) { if (domain != null) { _routes.last.domain = domain; @@ -105,29 +95,170 @@ class Router { return this; } + /// Specifies a parameter as an integer. + Router whereInt(String paramName) { + _routes.last.paramTypes ??= {}; + _routes.last.paramTypes![paramName] = int; + return this; + } + + /// Specifies a parameter as a string. + Router whereString(String paramName) { + _routes.last.paramTypes ??= {}; + _routes.last.paramTypes![paramName] = String; + return this; + } + + /// Specifies a custom regular expression for a parameter. + Router where(String paramName, String regex) { + _routes.last.regex ??= {}; + _routes.last.regex![paramName] = regex; + return this; + } + + /// Adds a GET route. + static Router get(String path, Function action) => + _addRoute(HttpRequestMethod.get, path, action); + + /// Adds a POST route. + static Router post(String path, Function action) => + _addRoute(HttpRequestMethod.post, path, action); + + /// Adds a PUT route. + static Router put(String path, Function action) => + _addRoute(HttpRequestMethod.put, path, action); + + /// Adds a PATCH route. + static Router patch(String path, Function action) => + _addRoute(HttpRequestMethod.patch, path, action); + + /// Adds a DELETE route. + static Router delete(String path, Function action) => + _addRoute(HttpRequestMethod.delete, path, action); + + /// Adds an OPTIONS route. + static Router options(String path, Function action) => + _addRoute(HttpRequestMethod.options, path, action); + + /// Adds a PURGE route. + static Router purge(String path, Function action) => + _addRoute(HttpRequestMethod.purge, path, action); + + /// Adds a COPY route. + static Router copy(String path, Function action) => + _addRoute(HttpRequestMethod.copy, path, action); + + /// Adds a LINK route. + static Router link(String path, Function action) => + _addRoute(HttpRequestMethod.link, path, action); + + /// Adds an UNLINK route. + static Router unlink(String path, Function action) => + _addRoute(HttpRequestMethod.unlink, path, action); + + /// Adds a LOCK route. + static Router lock(String path, Function action) => + _addRoute(HttpRequestMethod.lock, path, action); + + /// Adds an UNLOCK route. + static Router unlock(String path, Function action) => + _addRoute(HttpRequestMethod.unlock, path, action); + + /// Adds a PROPFIND route. + static Router propfind(String path, Function action) => + _addRoute(HttpRequestMethod.propfind, path, action); + + /// Adds a route that responds to any HTTP method. + static Router any(String path, Function action) { + Router router = Router(); + for (HttpRequestMethod method in HttpRequestMethod.values) { + router + ._addRouteInternal(method, path, action) + .middleware(router._groupMiddleware) + .domain(router._groupDomain) + .prefix(router._groupPrefix); + } + return router; + } + + /// Adds a set of resource routes. + /// + /// The action parameter should be an instance of a controller with methods: + /// - index + /// - create + /// - store + /// - show + /// - edit + /// - update + /// - destroy + static Router resource(String path, dynamic action) { + Router router = Router(); + Router.get(path, action.index) + .middleware(router._groupMiddleware) + .domain(router._groupDomain) + .prefix(router._groupPrefix); + + Router.get("$path/create", action.create) + .middleware(router._groupMiddleware) + .domain(router._groupDomain) + .prefix(router._groupPrefix); + + Router.post(path, action.store) + .middleware(router._groupMiddleware) + .domain(router._groupDomain) + .prefix(router._groupPrefix); + + Router.get("$path/{id}", action.show) + .middleware(router._groupMiddleware) + .domain(router._groupDomain) + .prefix(router._groupPrefix) + .whereInt('id'); + + Router.get("$path/{id}/edit", action.edit) + .middleware(router._groupMiddleware) + .domain(router._groupDomain) + .prefix(router._groupPrefix) + .whereInt('id'); + + Router.put("$path/{id}", action.update) + .middleware(router._groupMiddleware) + .domain(router._groupDomain) + .prefix(router._groupPrefix) + .whereInt('id'); + + Router.delete("$path/{id}", action.destroy) + .middleware(router._groupMiddleware) + .domain(router._groupDomain) + .prefix(router._groupPrefix) + .whereInt('id'); + + return router; + } + + /// Adds a websocket route. static void websocket( String path, Function(WebSocketEvent) eventCallBack, { List? middleware, }) { - eventCallBack(WebSocketHandler().websocketRoute( - path, - middleware: middleware, - )); + eventCallBack( + WebSocketHandler().websocketRoute(path, middleware: middleware)); } + /// Groups a set of routes under a common prefix, middleware, and/or domain. static void group( Function callBack, { String? prefix, List? middleware, String? domain, }) { - Router()._groupPrefix = prefix; - Router()._groupMiddleware = middleware; - Router()._groupDomain = domain; + Router router = Router(); + router._groupPrefix = prefix; + router._groupMiddleware = middleware; + router._groupDomain = domain; callBack(); - Router()._groupPrefix = null; - Router()._groupMiddleware = null; - Router()._groupDomain = null; + router._groupPrefix = null; + router._groupMiddleware = null; + router._groupDomain = null; } } diff --git a/lib/src/server/base_http_server.dart b/lib/src/server/base_http_server.dart index a5c72b3..cf81a1d 100644 --- a/lib/src/server/base_http_server.dart +++ b/lib/src/server/base_http_server.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'dart:isolate'; +import 'package:vania/src/extensions/date_time_aws_format.dart'; import 'package:vania/src/http/request/request_handler.dart'; import 'package:vania/vania.dart'; @@ -89,7 +90,22 @@ class BaseHttpServer { ); } - httpServer?.listen(httpRequestHandler); + httpServer?.listen((HttpRequest request) async { + var startTime = DateTime.now(); + var requestUri = request.uri.path; + var starteRequest = startTime.format(); + + await httpRequestHandler(request); + + var endTime = DateTime.now(); + var duration = endTime.difference(startTime).inMilliseconds; + var requestedPath = requestUri.isNotEmpty + ? requestUri.padRight(118 - requestUri.length, '.') + : ''.padRight(118, '.'); + if (env('APP_DEBUG')) { + print('$starteRequest $requestedPath ~ ${duration}ms'); + } + }); if (env('APP_DEBUG')) { if (env('APP_SECURE')) { diff --git a/lib/src/server/initialize_config.dart b/lib/src/server/initialize_config.dart index 1da2a61..07c0aa8 100644 --- a/lib/src/server/initialize_config.dart +++ b/lib/src/server/initialize_config.dart @@ -1,4 +1,3 @@ -import 'package:vania/src/database/database_client.dart'; import 'package:vania/vania.dart'; Future initializeConfig(config) async {