@@ -167,6 +167,8 @@ TRALSecurity = class(TPersistent)
167167 property WhiteIPList: TStringList read GetWhiteIPList write SetWhiteIPList;
168168 end ;
169169
170+ TRALOnServerError = procedure(Error: Exception) of object ;
171+
170172 { TRALServer }
171173
172174 // Base class for HTTP Server components
@@ -182,6 +184,7 @@ TRALServer = class(TRALComponent)
182184 FIPConfig: TRALIPConfig;
183185 FListSubModules: TList;
184186 FPort: IntegerRAL;
187+ FRaiseError: boolean;
185188 FRoutes: TRALRoutes;
186189 FSecurity: TRALSecurity;
187190 FServerStatus: TStringList;
@@ -190,9 +193,10 @@ TRALServer = class(TRALComponent)
190193 FSSL: TRALSSL;
191194 FResponsePages: TRALResponsePages;
192195
193- FOnRequest: TRALOnReply;
194- FOnResponse: TRALOnReply;
195196 FOnClientBlock: TRALOnClientBlock;
197+ FOnRequest: TRALOnReply;
198+ FOnResponse: TRALOnReply;
199+ FOnServerError: TRALOnServerError;
196200 protected
197201 // Adds a fixed subroute from other components into server routes
198202 procedure AddSubRoute (ASubRoute: TRALModuleRoutes);
@@ -262,6 +266,8 @@ TRALServer = class(TRALComponent)
262266 property Port: IntegerRAL read FPort write SetPort;
263267 // Route configuration of the server, a.k.a endpoints
264268 property Routes: TRALRoutes read FRoutes write FRoutes;
269+ // Whether the server will raise error to the application or not (exception raise^), default value is false
270+ property RaiseError: boolean read FRaiseError write FRaiseError default false;
265271 // Security configurations of the server
266272 property Security: TRALSecurity read FSecurity write FSecurity;
267273 // Default text answered by the server without WebModule when requesting the route '/'
@@ -270,12 +276,15 @@ TRALServer = class(TRALComponent)
270276 property SessionTimeout: IntegerRAL read FSessionTimeout write SetSessionTimeout default 30000 ;
271277 // Boolean check to whether or not show the default text for route '/'
272278 property ShowServerStatus: boolean read FShowServerStatus write FShowServerStatus;
279+
273280 // Event fired whenever an incoming IP gets blocked by the server
274281 property OnClientBlock: TRALOnClientBlock read FOnClientBlock write FOnClientBlock;
275282 // Event fired whenever any request is received by the server
276283 property OnRequest: TRALOnReply read FOnRequest write FOnRequest;
277284 // Event fired whenever any response is sent by the server
278285 property OnResponse: TRALOnReply read FOnResponse write FOnResponse;
286+ // Event fired whenever any error happens inside the server
287+ property OnServerError: TRALOnServerError read FOnServerError write FOnServerError;
279288 end ;
280289
281290 { TRALModuleRoutes }
@@ -556,142 +565,149 @@ procedure TRALServer.ProcessCommands(ARequest: TRALRequest; AResponse: TRALRespo
556565begin
557566 if AResponse.StatusCode >= HTTP_BadRequest then
558567 Exit;
568+ try
569+ vRouteIsAuth := False;
559570
560- vRouteIsAuth := False;
561-
562- AResponse.ContentCompress := ARequest.AcceptCompress;
563- if AResponse.ContentCompress = ctNone then
564- AResponse.ContentCompress := FCompressType;
571+ AResponse.ContentCompress := ARequest.AcceptCompress;
572+ if AResponse.ContentCompress = ctNone then
573+ AResponse.ContentCompress := FCompressType;
565574
566- AResponse.ContentCripto := crNone;
567- if CriptoOptions.Key <> ' ' then
568- begin
569- AResponse.ContentCripto := ARequest.AcceptCripto;
570- AResponse.CriptoKey := CriptoOptions.Key;
571- end ;
575+ AResponse.ContentCripto := crNone;
576+ if CriptoOptions.Key <> ' ' then
577+ begin
578+ AResponse.ContentCripto := ARequest.AcceptCripto;
579+ AResponse.CriptoKey := CriptoOptions.Key;
580+ end ;
572581
573- vRoute := FRoutes.CanAnswerRoute(ARequest);
582+ vRoute := FRoutes.CanAnswerRoute(ARequest);
574583
575- vInt := 0 ;
576- while (vRoute = nil ) and (vInt < FListSubModules.Count) do
577- begin
578- vSubRoute := TRALModuleRoutes(FListSubModules.Items[vInt]);
579- vRoute := vSubRoute.CanAnswerRoute(ARequest, AResponse);
580- vInt := vInt + 1 ;
581- end ;
584+ vInt := 0 ;
585+ while (vRoute = nil ) and (vInt < FListSubModules.Count) do
586+ begin
587+ vSubRoute := TRALModuleRoutes(FListSubModules.Items[vInt]);
588+ vRoute := vSubRoute.CanAnswerRoute(ARequest, AResponse);
589+ vInt := vInt + 1 ;
590+ end ;
582591
583- if (vRoute = nil ) and (FAuthentication <> nil ) then
584- begin
585- vRoute := FAuthentication.CanAnswerRoute(ARequest, AResponse);
586- if vRoute <> nil then
587- vRouteIsAuth := True;
588- end ;
592+ if (vRoute = nil ) and (FAuthentication <> nil ) then
593+ begin
594+ vRoute := FAuthentication.CanAnswerRoute(ARequest, AResponse);
595+ if vRoute <> nil then
596+ vRouteIsAuth := True;
597+ end ;
589598
590- if Assigned(FOnRequest) then
591- FOnRequest(ARequest, AResponse);
599+ if Assigned(FOnRequest) then
600+ FOnRequest(ARequest, AResponse);
592601
593- if Assigned(vRoute) then
594- begin
595- CheckCORS(vRoute.IsMethodAllowed(amOPTIONS), vRoute.GetAllowMethods, ARequest, AResponse);
596- if ARequest.Method = amOPTIONS then
597- begin
598- if vRoute.IsMethodAllowed(amOPTIONS) then
599- goto aFIM
600- else
601- goto a404;
602- end
603- else if vRouteIsAuth then
602+ if Assigned(vRoute) then
604603 begin
605- FAuthentication.BeforeValidate(ARequest, AResponse);
606- goto aFIM;
607- end
608- else if vRoute.IsMethodAllowed(ARequest.Method) then
609- begin
610- if FAuthentication <> nil then
604+ CheckCORS(vRoute.IsMethodAllowed(amOPTIONS), vRoute.GetAllowMethods, ARequest, AResponse);
605+ if ARequest.Method = amOPTIONS then
611606 begin
612- if vRoute.IsMethodSkipped(ARequest.Method) then
613- begin
614- goto aOK;
615- end
607+ if vRoute.IsMethodAllowed(amOPTIONS) then
608+ goto aFIM
616609 else
610+ goto a404;
611+ end
612+ else if vRouteIsAuth then
613+ begin
614+ FAuthentication.BeforeValidate(ARequest, AResponse);
615+ goto aFIM;
616+ end
617+ else if vRoute.IsMethodAllowed(ARequest.Method) then
618+ begin
619+ if FAuthentication <> nil then
617620 begin
618- vCheckBruteForce := (rsoBruteForceProtection in Security.Options);
619- // client e valido se o numero de tentativas <= ao max de tentativas
620- vCheckBruteForceTries :=
621- (vCheckBruteForce and (Security.CheckBlockClientTry(
622- ARequest.ClientInfo.IP)));
623-
624- // devido algumas auths que adiciona o header realm
625- vCheck_Authentication := ValidateAuth(ARequest, AResponse);
626-
627- if vCheck_Authentication then
628- goto aOK
629- else if (vCheckBruteForceTries) or (AResponse.StatusCode = HTTP_Unauthorized) then
630- goto a401
621+ if vRoute.IsMethodSkipped(ARequest.Method) then
622+ begin
623+ goto aOK;
624+ end
631625 else
632- goto a403;
633- end ;
626+ begin
627+ vCheckBruteForce := (rsoBruteForceProtection in Security.Options);
628+ // client e valido se o numero de tentativas <= ao max de tentativas
629+ vCheckBruteForceTries :=
630+ (vCheckBruteForce and (Security.CheckBlockClientTry(
631+ ARequest.ClientInfo.IP)));
632+
633+ // devido algumas auths que adiciona o header realm
634+ vCheck_Authentication := ValidateAuth(ARequest, AResponse);
635+
636+ if vCheck_Authentication then
637+ goto aOK
638+ else if (vCheckBruteForceTries) or (AResponse.StatusCode = HTTP_Unauthorized) then
639+ goto a401
640+ else
641+ goto a403;
642+ end ;
643+ end
644+ else
645+ goto aOK;
634646 end
635647 else
636- goto aOK ;
648+ goto a403 ;
637649 end
650+ else if (ARequest.Query = ' /' ) and (FShowServerStatus) then
651+ goto aSTATUS
638652 else
639- goto a403;
640- end
641- else if (ARequest.Query = ' /' ) and (FShowServerStatus) then
642- goto aSTATUS
643- else
644- goto a404;
653+ goto a404;
645654
646- aSTATUS:
647- begin
648- CheckCORS(True, ' GET' , ARequest, AResponse);
649- if ARequest.Method <> amOPTIONS then
655+ aSTATUS:
650656 begin
651- vString := Trim(FServerStatus.Text);
652- if vString = EmptyStr then
653- vString := RALDefaultPage;
654- vString := StringReplace(vString, ' %ralengine%' , FEngine, [rfReplaceAll]);
655- AResponse.Answer(HTTP_OK, vString, rctTEXTHTML);
657+ CheckCORS(True, ' GET' , ARequest, AResponse);
658+ if ARequest.Method <> amOPTIONS then
659+ begin
660+ vString := Trim(FServerStatus.Text);
661+ if vString = EmptyStr then
662+ vString := RALDefaultPage;
663+ vString := StringReplace(vString, ' %ralengine%' , FEngine, [rfReplaceAll]);
664+ AResponse.Answer(HTTP_OK, vString, rctTEXTHTML);
665+ end ;
666+ goto aFIM;
656667 end ;
657- goto aFIM;
658- end ;
659668
660- aOK:
661- begin
662- Security.UnblockClient(ARequest.ClientInfo.IP);
663- vRoute.Execute(ARequest, AResponse);
664- goto aFIM;
665- end ;
669+ aOK:
670+ begin
671+ Security.UnblockClient(ARequest.ClientInfo.IP);
672+ vRoute.Execute(ARequest, AResponse);
673+ goto aFIM;
674+ end ;
666675
667- a401:
668- begin
669- Security.BlockClient(ARequest.ClientInfo.IP);
670- AResponse.Answer(HTTP_Unauthorized);
671- goto aFIM;
672- end ;
676+ a401:
677+ begin
678+ Security.BlockClient(ARequest.ClientInfo.IP);
679+ AResponse.Answer(HTTP_Unauthorized);
680+ goto aFIM;
681+ end ;
673682
674- a403:
675- begin
676- Security.BlockClient(ARequest.ClientInfo.IP);
677- if Assigned(FOnClientBlock) then
678- FOnClientBlock(Self, ARequest.ClientInfo.IP);
679- AResponse.Answer(HTTP_Forbidden);
680- goto aFIM;
681- end ;
683+ a403:
684+ begin
685+ Security.BlockClient(ARequest.ClientInfo.IP);
686+ if Assigned(FOnClientBlock) then
687+ FOnClientBlock(Self, ARequest.ClientInfo.IP);
688+ AResponse.Answer(HTTP_Forbidden);
689+ goto aFIM;
690+ end ;
682691
683- a404:
684- begin
685- AResponse.Answer(HTTP_NotFound);
686- goto aFIM;
687- end ;
692+ a404:
693+ begin
694+ AResponse.Answer(HTTP_NotFound);
695+ goto aFIM;
696+ end ;
688697
689- aFIM:
690- begin
691- if Assigned(FOnResponse) then
692- FOnResponse(ARequest, AResponse);
698+ aFIM:
699+ begin
700+ if Assigned(FOnResponse) then
701+ FOnResponse(ARequest, AResponse);
693702
694- ARequest.Params.ClearParams;
703+ ARequest.Params.ClearParams;
704+ end ;
705+ except
706+ on e: exception do
707+ if assigned(OnServerError) then
708+ OnServerError(e)
709+ else if RaiseError then
710+ raise;
695711 end ;
696712end ;
697713
0 commit comments