Recent

Author Topic: [SOLVED] duplicate route doesn't trigger exception  (Read 2380 times)

Чебурашка

  • Hero Member
  • *****
  • Posts: 588
  • СЛАВА УКРАЇНІ! / Slava Ukraïni!
[SOLVED] duplicate route doesn't trigger exception
« on: February 09, 2022, 02:13:43 pm »
Hello,
The following code does not show any exception here, but I would expect this to happen.
Any ideas?

me@debian:~/Documents/dev$ fpc -version
[0.004] Free Pascal Compiler version 3.0.4+dfsg-22 [2019/01/24] for x86_64
[0.004] Copyright (c) 1993-2017 by Florian Klaempfl and others


Code: Pascal  [Select][+][-]
  1. program project1;
  2.  
  3.  
  4. uses
  5.  
  6.   Classes, SysUtils
  7.  
  8.   , HTTPDefs
  9.   , httproute;
  10.  
  11. procedure PostCallback1(req: TRequest; res: TResponse);
  12. begin
  13.   // Actions on post event
  14. end;
  15. procedure PostCallback2(req: TRequest; res: TResponse);
  16. begin
  17.   // Actions on post event
  18. end;
  19.  
  20. begin
  21.   try
  22.     HTTPRouter.RegisterRoute('/post' , TRouteMethod.rmPost, @PostCallback1, False);
  23.     HTTPRouter.RegisterRoute('/post' , TRouteMethod.rmPost, @PostCallback2, False);
  24.   except
  25.     on E: Exception do begin
  26.       Writeln(E.Message);
  27.     end;
  28.   end;
  29. end.
  30.  

Thank you



« Last Edit: February 10, 2022, 02:26:54 pm by tt »
FPC 3.2.0/Lazarus 2.0.10+dfsg-4+b2 on Debian 11.5
FPC 3.2.2/Lazarus 2.2.0 on Windows 10 Pro 21H2

Thaddy

  • Hero Member
  • *****
  • Posts: 17213
  • Ceterum censeo Trump esse delendam
Re: duplicate route doesn't trigger exception
« Reply #1 on: February 09, 2022, 05:00:17 pm »
Empty procs are removed by default, so try -O-
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

Чебурашка

  • Hero Member
  • *****
  • Posts: 588
  • СЛАВА УКРАЇНІ! / Slava Ukraïni!
Re: duplicate route doesn't trigger exception
« Reply #2 on: February 09, 2022, 05:08:34 pm »
Same.

Anyway the problem is in RegisterRoute being called twice with same address/routemethod not in the fact that the callbacks are wiped because of optimization.

Btw does really optimization wipe out a method that is referenced?


Code: Pascal  [Select][+][-]
  1.  
  2. program project2;
  3.  
  4.  
  5. uses
  6.  
  7.   Classes, SysUtils
  8.  
  9.   , HTTPDefs
  10.   , httproute;
  11.  
  12. procedure PostCallback1(req: TRequest; res: TResponse);
  13. begin
  14.   Writeln('hello');
  15. end;
  16. procedure PostCallback2(req: TRequest; res: TResponse);
  17. begin
  18.   Writeln('world');
  19. end;
  20.  
  21. begin
  22.   try
  23.     HTTPRouter.RegisterRoute('/post' , TRouteMethod.rmPost, @PostCallback1, False);
  24.     HTTPRouter.RegisterRoute('/post' , TRouteMethod.rmPost, @PostCallback2, False);
  25.   except
  26.     on E: Exception do begin
  27.       Writeln(E.Message);
  28.     end;
  29.   end;
  30. end.
  31.  
  32.  
« Last Edit: February 09, 2022, 05:11:11 pm by tt »
FPC 3.2.0/Lazarus 2.0.10+dfsg-4+b2 on Debian 11.5
FPC 3.2.2/Lazarus 2.2.0 on Windows 10 Pro 21H2

irawan

  • New Member
  • *
  • Posts: 13
Re: duplicate route doesn't trigger exception
« Reply #3 on: February 10, 2022, 03:45:21 am »
PostCallback2 replaces PostCallback1. so there is no exception occured.

Чебурашка

  • Hero Member
  • *****
  • Posts: 588
  • СЛАВА УКРАЇНІ! / Slava Ukraïni!
Re: duplicate route doesn't trigger exception
« Reply #4 on: February 10, 2022, 08:54:06 am »
So HTTPRouter is intended to be callable twice with the same couple ('/path', rmPost)?

Then what is the meaning of the inner method CheckDuplicates? For what I understand such a method should trigger a exception when '/path', rmPost already exists in the routes set.

Apparently I am wrong can some one explain?


Code: Pascal  [Select][+][-]
  1. function THTTPRouter.CreateHTTPRoute(AClass : THTTPRouteClass; const APattern: String;AMethod: TRouteMethod; IsDefault: Boolean) : THTTPRoute;
  2.  
  3. begin
  4.   CheckDuplicate(APattern,AMethod,isDefault);
  5.   Result:=AClass.Create(FRoutes);
  6.   With Result do
  7.     begin
  8.     URLPattern:=APattern;
  9.     Default:=IsDefault;
  10.     Method:=AMethod;
  11.     end;
  12. end;
  13.  
  14. procedure THTTPRouter.CheckDuplicate(APattern: String; AMethod: TRouteMethod;
  15.   isDefault: Boolean);
  16. Var
  17.   I,DI : Integer;
  18.   R : THTTPRoute;
  19.  
  20. begin
  21.   DI:=-1;
  22.   For I:=0 to FRoutes.Count-1 do
  23.     begin
  24.     R:=FRoutes[I];
  25.     if R.Default then
  26.       DI:=I;
  27.     if R.Matches(APattern,AMethod) then
  28.       Raise EHTTPRoute.CreateFmt(EDuplicateRoute,[APattern,RouteMethodToString(AMethod)]);
  29.     end;
  30.   if isDefault and (DI<>-1) then
  31.     Raise EHTTPRoute.CreateFmt(EDuplicateDefaultRoute,[APattern,RouteMethodToString(AMethod)]);
  32. end;
  33.  
  34. function THTTPRoute.Matches(const APattern: String; AMethod: TRouteMethod
  35.   ): Boolean;
  36. begin
  37.   Result:=(CompareText(URLPattern,APattern)=0)
  38.           and ((Method=rmAll) or (AMethod=Method))
  39. end;
  40.  
  41.  
FPC 3.2.0/Lazarus 2.0.10+dfsg-4+b2 on Debian 11.5
FPC 3.2.2/Lazarus 2.2.0 on Windows 10 Pro 21H2

PascalDragon

  • Hero Member
  • *****
  • Posts: 6008
  • Compiler Developer
Re: duplicate route doesn't trigger exception
« Reply #5 on: February 10, 2022, 09:09:19 am »
Empty procs are removed by default, so try -O-

Not if they are used (either by calling them or referencing them), which is the case here.

Чебурашка

  • Hero Member
  • *****
  • Posts: 588
  • СЛАВА УКРАЇНІ! / Slava Ukraïni!
Re: duplicate route doesn't trigger exception
« Reply #6 on: February 10, 2022, 09:12:10 am »
Btw does really optimization wipe out a method that is referenced?

Thanks PascalDragon
FPC 3.2.0/Lazarus 2.0.10+dfsg-4+b2 on Debian 11.5
FPC 3.2.2/Lazarus 2.2.0 on Windows 10 Pro 21H2

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: duplicate route doesn't trigger exception
« Reply #7 on: February 10, 2022, 12:59:07 pm »
So HTTPRouter is intended to be callable twice with the same couple ('/path', rmPost)?

Then what is the meaning of the inner method CheckDuplicates? For what I understand such a method should trigger a exception when '/path', rmPost already exists in the routes set.

Apparently I am wrong can some one explain?


Code: Pascal  [Select][+][-]
  1. function THTTPRouter.CreateHTTPRoute(AClass : THTTPRouteClass; const APattern: String;AMethod: TRouteMethod; IsDefault: Boolean) : THTTPRoute;
  2.  
  3. begin
  4.   CheckDuplicate(APattern,AMethod,isDefault);
  5.   Result:=AClass.Create(FRoutes);
  6.   With Result do
  7.     begin
  8.     URLPattern:=APattern;
  9.     Default:=IsDefault;
  10.     Method:=AMethod;
  11.     end;
  12. end;
  13.  
  14. procedure THTTPRouter.CheckDuplicate(APattern: String; AMethod: TRouteMethod;
  15.   isDefault: Boolean);
  16. Var
  17.   I,DI : Integer;
  18.   R : THTTPRoute;
  19.  
  20. begin
  21.   DI:=-1;
  22.   For I:=0 to FRoutes.Count-1 do
  23.     begin
  24.     R:=FRoutes[I];
  25.     if R.Default then
  26.       DI:=I;
  27.     if R.Matches(APattern,AMethod) then
  28.       Raise EHTTPRoute.CreateFmt(EDuplicateRoute,[APattern,RouteMethodToString(AMethod)]);
  29.     end;
  30.   if isDefault and (DI<>-1) then
  31.     Raise EHTTPRoute.CreateFmt(EDuplicateDefaultRoute,[APattern,RouteMethodToString(AMethod)]);
  32. end;
  33.  
  34. function THTTPRoute.Matches(const APattern: String; AMethod: TRouteMethod
  35.   ): Boolean;
  36. begin
  37.   Result:=(CompareText(URLPattern,APattern)=0)
  38.           and ((Method=rmAll) or (AMethod=Method))
  39. end;
  40.  
  41.  

You are not wrong. The class changes the first pattern from '/post' to 'post/' before saving it. Later when it checks for double, it compares the second pattern with the modified pattern. Of course they don't match.

The change happens inside THTTPRoute.SetURLPattern:
Code: Pascal  [Select][+][-]
  1. procedure THTTPRoute.SetURLPattern(AValue: String);
  2.  
  3. Var
  4.   V : String;
  5.  
  6. begin
  7.   V:=IncludeHTTPPathDelimiter(AValue);
  8.   if (V<>'') and (V<>'/') and (V[1]='/') then
  9.     Delete(V,1,1);
  10.   if FURLPattern=V then Exit;
  11.   FURLPattern:=V;
  12. end;

To trigger the exception, change your code to:
Code: Pascal  [Select][+][-]
  1.     HTTPRouter.RegisterRoute('post/' , TRouteMethod.rmPost, @PostCallback1, False);
  2.     HTTPRouter.RegisterRoute('post/' , TRouteMethod.rmPost, @PostCallback2, False);

PascalDragon

  • Hero Member
  • *****
  • Posts: 6008
  • Compiler Developer
Re: duplicate route doesn't trigger exception
« Reply #8 on: February 10, 2022, 01:34:46 pm »
You are not wrong. The class changes the first pattern from '/post' to 'post/' before saving it. Later when it checks for double, it compares the second pattern with the modified pattern. Of course they don't match.

That should be reported as a bug then.

Чебурашка

  • Hero Member
  • *****
  • Posts: 588
  • СЛАВА УКРАЇНІ! / Slava Ukraïni!
Re: duplicate route doesn't trigger exception
« Reply #9 on: February 10, 2022, 01:40:22 pm »
Probably is a small bug then...

in page

https://wiki.freepascal.org/fphttpserver

thers an example telling

Code: Pascal  [Select][+][-]
  1. [...]
  2.   HTTPRouter.registerRoute('/', @route1);
  3.   HTTPRouter.registerRoute('/2', @route2);
  4. [...]
  5.  

so people thinks / should be normally placed at beginning of path as I did (just taking there code as satring point).

FPC 3.2.0/Lazarus 2.0.10+dfsg-4+b2 on Debian 11.5
FPC 3.2.2/Lazarus 2.2.0 on Windows 10 Pro 21H2

Чебурашка

  • Hero Member
  • *****
  • Posts: 588
  • СЛАВА УКРАЇНІ! / Slava Ukraïni!
Re: duplicate route doesn't trigger exception
« Reply #10 on: February 10, 2022, 02:00:49 pm »
That should be reported as a bug then.

Reported.
FPC 3.2.0/Lazarus 2.0.10+dfsg-4+b2 on Debian 11.5
FPC 3.2.2/Lazarus 2.2.0 on Windows 10 Pro 21H2

Чебурашка

  • Hero Member
  • *****
  • Posts: 588
  • СЛАВА УКРАЇНІ! / Slava Ukraïni!
FPC 3.2.0/Lazarus 2.0.10+dfsg-4+b2 on Debian 11.5
FPC 3.2.2/Lazarus 2.2.0 on Windows 10 Pro 21H2

 

TinyPortal © 2005-2018