Skip to content

Commit

Permalink
Merge pull request #168 from javad-zobeidi/dev
Browse files Browse the repository at this point in the history
Fixed bugs and Refactor methods
  • Loading branch information
javad-zobeidi authored Feb 3, 2025
2 parents d9aebd2 + 042175b commit 09f7c96
Show file tree
Hide file tree
Showing 24 changed files with 502 additions and 478 deletions.
24 changes: 11 additions & 13 deletions lib/src/application.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import 'package:vania/src/container.dart';
import 'package:vania/src/ioc_container.dart';
import 'package:vania/src/localization_handler/localization.dart';
import 'package:vania/src/server/base_http_server.dart';
import 'package:vania/vania.dart';

import 'http/request/request_handler.dart';
import 'http/session/session_manager.dart';

class Application extends Container {
static Application? _singleton;

Expand All @@ -17,27 +21,21 @@ class Application extends Container {

Application._internal();

late BaseHttpServer server;
late BaseHttpServer _server;

Future<void> initialize({required Map<String, dynamic> config}) async {
IoCContainer().register<RequestHandler>(() => RequestHandler());
IoCContainer()
.register<SessionManager>(() => SessionManager(), singleton: true);
if (env('APP_KEY') == '' || env('APP_KEY') == null) {
throw Exception('Key not found');
}

server = BaseHttpServer(config: config);

if (env<bool>('ISOLATE', false)) {
await server.spawnIsolates(env<int>('ISOLATE_NUMBER', 1));
} else {
server.startServer();
}
_server = BaseHttpServer(config: config);
_server.startServer();
}

Future<void> close() async {
if (env<bool>('ISOLATE', false)) {
server.killAll();
} else {
server.httpServer?.close();
}
_server.httpServer?.close();
}
}
2 changes: 1 addition & 1 deletion lib/src/authentication/authenticate.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class Authenticate extends Middleware {
if (loggedIn && guard.isNotEmpty) {
Map<String, dynamic> user =
await getSession<Map<String, dynamic>?>('auth_user') ?? {};
Auth().guard(guard).login(user[guard], true);
Auth().guard(guard).login(user[guard]);
} else {
throw Unauthenticated(
message: loginPath,
Expand Down
18 changes: 2 additions & 16 deletions lib/src/authentication/authentication.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class Auth {

bool get loggedIn => _loggedIn;

Map<String, dynamic>? user() => _user[_userGuard];
Map<String, dynamic> user() => _user[_userGuard];

dynamic id() => _user[_userGuard]['id'] ?? _user[_userGuard]['_id'];

Expand Down Expand Up @@ -70,14 +70,6 @@ class Auth {
await deleteSession('auth_guard');
await deleteSession('auth_user');
_loggedIn = false;
if (_currentToken.isNotEmpty) {
try {
await PersonalAccessTokens()
.query()
.where('token', '=', md5.convert(utf8.encode(_currentToken)))
.update({'deleted_at': DateTime.now()});
} catch (_) {}
}
}

/// Updates the current session with the given user and guard.
Expand All @@ -91,13 +83,7 @@ class Auth {
Future<void> _updateSession() async {
await setSession('logged_in', true);
await setSession('auth_guard', _userGuard);
Map<String, dynamic> user =
await getSession<Map<String, dynamic>?>('auth_user') ?? {};
if (_user != user) {
await deleteSession('auth_user');
await setSession('auth_user', _user);
}

await setSession('auth_user', _user);
_loggedIn = true;
}

Expand Down
14 changes: 14 additions & 0 deletions lib/src/authentication/redirect_if_authenticated.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import 'package:vania/vania.dart';

class RedirectIfAuthenticated extends Middleware {
final String path;
RedirectIfAuthenticated({required this.path});

@override
Future handle(Request req) async {
bool loggedIn = await getSession<bool?>('logged_in') ?? false;
if (loggedIn) {
return Response.redirect(path);
}
}
}
6 changes: 0 additions & 6 deletions lib/src/http/middleware/middleware.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,8 @@ import 'package:vania/vania.dart';

abstract class Middleware {
Future handle(Request req);

@Deprecated('Will be deleted in the next versions')
Middleware? next;
}

abstract class WebSocketMiddleware {
Future handle(HttpRequest req);

@Deprecated('Will be deleted in the next versions')
WebSocketMiddleware? next;
}
24 changes: 20 additions & 4 deletions lib/src/http/request/request.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ class Request {
Map<String, dynamic> body = <String, dynamic>{};
final Map<String, dynamic> _cookies = <String, dynamic>{};

List<CustomValidationRule>? _customRules;

Request setCustomRule(List<CustomValidationRule> customRule) {
_customRules = customRule;
return this;
}

/// Gets a cookie by name and casts it to type [T].
///
/// If the cookie doesn't exist, it returns `null`.
Expand Down Expand Up @@ -318,8 +325,10 @@ class Request {
return header(HttpHeaders.refererHeader);
}

void validate(dynamic rules,
[Map<String, String> messages = const <String, String>{}]) {
void validate(
dynamic rules, [
Map<String, String> messages = const <String, String>{},
]) {
assert(rules is Map<String, String> || rules is List<Validation>,
'Rules must be either Map<String, String> or List<Validation>.');
TemplateEngine().sessionErrors.clear();
Expand All @@ -330,9 +339,16 @@ class Request {
}
}

void _validate(Map<String, String> rules,
[Map<String, String> messages = const <String, String>{}]) {
void _validate(
Map<String, String> rules, [
Map<String, String> messages = const <String, String>{},
]) {
Validator validator = Validator(data: all());

if (_customRules != null) {
validator.customRule(_customRules!);
}

if (messages.isNotEmpty) {
validator.setNewMessages(messages);
}
Expand Down
180 changes: 91 additions & 89 deletions lib/src/http/request/request_handler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'package:vania/src/exception/not_found_exception.dart';
import 'package:vania/src/exception/unauthenticated.dart';
import 'package:vania/src/http/controller/controller_handler.dart';
import 'package:vania/src/http/middleware/middleware_handler.dart';
import 'package:vania/src/ioc_container.dart';
import 'package:vania/src/route/route_data.dart';
import 'package:vania/src/route/route_handler.dart';
import 'package:vania/src/route/route_history.dart';
Expand All @@ -16,110 +17,111 @@ import 'package:vania/vania.dart';

import '../session/session_manager.dart';

/// Handles HTTP requests, determining if the request is a WebSocket upgrade or
/// a standard HTTP request. If it's a WebSocket request, it delegates handling
/// to the WebSocketHandler; otherwise, it processes the request by checking
/// CORS, handling routes, invoking middleware, and executing the appropriate
/// controller action. The function also manages session initiation and logs
/// request details in debug mode.
///
/// Throws:
/// - [BaseHttpResponseException] if there is an issue with the HTTP response.
/// - [InvalidArgumentException] if an invalid argument is encountered.
Future httpRequestHandler(HttpRequest req) async {
/// Check the incoming request is web socket or not
if (env<bool>('APP_WEBSOCKET', false) &&
WebSocketTransformer.isUpgradeRequest(req)) {
await SessionManager().sessionStart(req, req.response);
WebSocketHandler().handler(req);
} else {
bool isHtml = req.headers.value('accept').toString().contains('html');
try {
HttpCors(req);
RouteData? route = httpRouteHandler(req);
DateTime startTime = DateTime.now();
String requestUri = req.uri.path;
String starteRequest = startTime.format();
class RequestHandler {
/// Handles HTTP requests, determining if the request is a WebSocket upgrade or
/// a standard HTTP request. If it's a WebSocket request, it delegates handling
/// to the WebSocketHandler; otherwise, it processes the request by checking
/// CORS, handling routes, invoking middleware, and executing the appropriate
/// controller action. The function also manages session initiation and logs
/// request details in debug mode.
///
/// Throws:
/// - [BaseHttpResponseException] if there is an issue with the HTTP response.
/// - [InvalidArgumentException] if an invalid argument is encountered.
Future handle(HttpRequest req) async {
/// Check the incoming request is web socket or not
if (env<bool>('APP_WEBSOCKET', false) &&
WebSocketTransformer.isUpgradeRequest(req)) {
WebSocketHandler().handler(req);
} else {
bool isHtml = req.headers.value('accept').toString().contains('html');
try {
HttpCors(req);
RouteData? route = httpRouteHandler(req);
DateTime startTime = DateTime.now();
String requestUri = req.uri.path;
String starteRequest = startTime.format();

if (route != null) {
/// Check if cors is enabled
if (route != null) {
Request request = Request.from(request: req, route: route);
await request.extractBody();

Request request = Request.from(request: req, route: route);
await request.extractBody();
if (isHtml) {
TemplateEngine().formData.addAll(request.all());
await IoCContainer()
.resolve<SessionManager>()
.sessionStart(req, req.response);
RouteHistory().updateRouteHistory(req);
}

if (isHtml) {
TemplateEngine().formData.addAll(request.all());
await SessionManager().sessionStart(req, req.response);
RouteHistory().updateRouteHistory(req);
}

/// check if pre middleware exist and call it
if (route.preMiddleware.isNotEmpty) {
await middlewareHandler(route.preMiddleware, request);
}
/// check if pre middleware exist and call it
if (route.preMiddleware.isNotEmpty) {
await middlewareHandler(route.preMiddleware, request);
}

/// Controller and method handler
ControllerHandler().create(
route: route,
request: request,
);
/// Controller and method handler
ControllerHandler().create(
route: route,
request: request,
);

if (env<bool>('APP_DEBUG')) {
var endTime = DateTime.now();
var duration = endTime.difference(startTime).inMilliseconds;
var requestedPath = requestUri.isNotEmpty
? requestUri.padRight(118 - requestUri.length, '.')
: ''.padRight(118, '.');
print('$starteRequest $requestedPath ~ ${duration}ms');
if (env<bool>('APP_DEBUG')) {
var endTime = DateTime.now();
var duration = endTime.difference(startTime).inMilliseconds;
var requestedPath = requestUri.isNotEmpty
? requestUri.padRight(118 - requestUri.length, '.')
: ''.padRight(118, '.');
print('$starteRequest $requestedPath ~ ${duration}ms');
}
}
}
} on BaseHttpResponseException catch (error) {
if (error is NotFoundException && isHtml) {
if (File('lib/view/template/errors/404.html').existsSync()) {
return view('errors/404').makeResponse(req.response);
} on BaseHttpResponseException catch (error) {
if (error is NotFoundException && isHtml) {
if (File('lib/view/template/errors/404.html').existsSync()) {
return view('errors/404').makeResponse(req.response);
}
}
}

if (error is InternalServerError && isHtml) {
if (File('lib/view/template/errors/500.html').existsSync()) {
return view('errors/500').makeResponse(req.response);
if (error is InternalServerError && isHtml) {
if (File('lib/view/template/errors/500.html').existsSync()) {
return view('errors/500').makeResponse(req.response);
}
}
}

if (error is PageExpiredException && isHtml) {
if (File('lib/view/template/errors/419.html').existsSync()) {
return view('errors/419').makeResponse(req.response);
if (error is PageExpiredException && isHtml) {
if (File('lib/view/template/errors/419.html').existsSync()) {
return view('errors/419').makeResponse(req.response);
}
}
}

if (error is Unauthenticated && isHtml) {
return Response.redirect(error.message).makeResponse(req.response);
}
if (error is Unauthenticated && isHtml) {
return Response.redirect(error.message).makeResponse(req.response);
}

error
.response(
isHtml,
)
.makeResponse(req.response);
} on InvalidArgumentException catch (e) {
Logger.log(e.message, type: Logger.ERROR);
_response(req, e.message);
} catch (e) {
Logger.log(e.toString(), type: Logger.ERROR);
_response(req, e.toString());
error
.response(
isHtml,
)
.makeResponse(req.response);
} on InvalidArgumentException catch (e) {
Logger.log(e.message, type: Logger.ERROR);
_response(req, e.message);
} catch (e) {
Logger.log(e.toString(), type: Logger.ERROR);
_response(req, e.toString());
}
}
}
}

void _response(req, message) {
if (req.headers.value('accept').toString().contains('html')) {
Response.html(message).makeResponse(req.response);
} else {
Response.json(
{
"message": message,
},
400,
).makeResponse(req.response);
void _response(req, message) {
if (req.headers.value('accept').toString().contains('html')) {
Response.html(message).makeResponse(req.response);
} else {
Response.json(
{
"message": message,
},
400,
).makeResponse(req.response);
}
}
}
Loading

0 comments on commit 09f7c96

Please sign in to comment.