Recent

Author Topic: TFPHTTPServer freezing after Edge browser request  (Read 712 times)

Abrax

  • New member
  • *
  • Posts: 7
TFPHTTPServer freezing after Edge browser request
« on: February 05, 2021, 07:30:37 pm »
Dear All,

I have a very strange phenomenon on my embedded webserver.
 
It is a console application, which uses a common threaded webserver by the "Pure Hand Coding" way. The debug version is running locally on a Win10x64 system which is connected through a CISCO VPN to a remotely PGSQL database, running on a RPi4 in a corporate intranet. The release version is running on the same RPi as the PGSQL. In this latter case I can access the webserver through the VPN as well.
 
The served html pages are created in severeal ways: from spreadsheet's stream output; static .htlm files from the file system; or assembled by code.
The starting page is coming from a GET request, any other pages come from POST requests.

After starting the program, calling the http://localhost:8080 (or http://10.xxx.xxx.xxx:8080 in release) in the IE11 or in the Firefox browser, everything works fine.
The browsers load the start page, and I can navigate between pages which use the
Code: HTML5  [Select][+][-]
  1. <form method="post"  target="_self"><button "type="submit"...>...</button></form>
request without problem.
However, things only work well, until I open the page in an Edge browser.
As soon as I open the http://localhost:8080 from an Edge browser, the server doesn't respond to the IE11 and Firefox requests anymore, until the Edge request the same page as the IE or the Firefox.

Let's see an example!
1. We have 3 pages. The Firefox can navigate between them 1->2->3->1.
2. We start the Edge with page1.
3. Back to the Firefox we try to navigete to page 2, but it can't, until we choose the page 2 on Edge too.

When on the web page I push the button which fires the POST request several times, while the IE11 is waiting locked, I get an "Error reading data from the socket" (code 10054) from the TFPHTTPConnection object on the application console.

I have no idea how to overcome this situation. I welcome any suggestion or help.



Code: Pascal  [Select][+][-]
  1. program webl;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses
  6.   {$IFDEF UNIX}
  7.   //{$IFDEF UseCThreads}
  8.   cthreads,
  9.   {$ENDIF}//{$ENDIF}
  10.   Classes, SysUtils, CustApp//, ...
  11.   { you can add units after this };
  12.  
  13. var
  14.   Application: TMyApplication;
  15. begin
  16.   Application:=TMyApplication.Create(nil);
  17.   Application.Title:='WebL';
  18.   Application.Run;
  19.   Application.Free;
  20. end.


Code: Pascal  [Select][+][-]
  1. unit webserver;
  2.  
  3. {$mode delphi}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils,
  9.   fphttpserver, HTTPDefs, httpprotocol;
  10.  
  11. type
  12.  
  13.     { THTTPServerThread }
  14.  
  15.     THTTPServerThread = class(TThread)
  16.   private
  17.     //FServer : TFPHTTPServer;
  18.   public
  19.     FServer : TFPHTTPServer;
  20.     OnRequest1: THTTPServerRequestHandler;
  21.     OnRequestError1 : TRequestErrorHandler;
  22.     OnAcceptIdle1: TNotifyEvent;
  23.     constructor Create(APort : Word; const OnRequest : THTTPServerRequestHandler; const OnRequestError : TRequestErrorHandler; const OnAcceptIdle: TNotifyEvent);
  24.     procedure Execute; override;
  25.     procedure DoTerminate; override;
  26.   end;
  27.  
  28. implementation
  29.  
  30. constructor THTTPServerThread.Create(APort: Word; const OnRequest: THTTPServerRequestHandler; const OnRequestError : TRequestErrorHandler; const OnAcceptIdle: TNotifyEvent);
  31. begin
  32.   OnRequest1:=OnRequest;
  33.   OnRequestError1:=OnRequestError;
  34.   OnAcceptIdle1:=OnAcceptIdle;
  35.  
  36.   FServer:=TFPHTTPServer.Create(Nil);
  37.   FServer.Port:=APort;
  38.   FServer.OnRequest:=OnRequest;
  39.   FServer.OnRequestError:=OnRequestError;
  40.  
  41.   inherited Create(False);
  42. end;
  43.  
  44. procedure THTTPServerThread.Execute;
  45. begin
  46.   try
  47.     FServer.Active:=True;
  48.   finally
  49.     FreeAndNil(FServer);
  50.   end;
  51. end;
  52.  
  53. procedure THTTPServerThread.DoTerminate;
  54. begin
  55.   inherited DoTerminate;
  56.   FServer.Active:=False;
  57. end;
  58.  
  59. end.
  60.  


Code: Pascal  [Select][+][-]
  1. unit webmodul;
  2.  
  3. {$mode delphi}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Math, //StdCtrls,
  9.   //Graphics,
  10.   fphttpserver, HTTPDefs, httpprotocol, fphttpapp, fpwebfile, webserver, fpmimetypes,
  11.   htmlconttype, {...};
  12.  
  13.   TWebModul = class(TObject)
  14.   private
  15.     FServer1 : THTTPServerThread;
  16.     procedure DoHandleRequest (Sender: TObject; var ARequest: TFPHTTPConnectionRequest; var AResponse : TFPHTTPConnectionResponse);
  17.     procedure DoHandReqError(Sender : TObject; E : Exception);
  18.     procedure DoAcceptIdle (Sender: TObject);
  19.   protected
  20.     {...}
  21.   public
  22.     constructor Create(AdatModule: TDataModule1);overload;
  23.     destructor Destroy; override;
  24.   published
  25.   end;
  26.  
  27. implementation
  28. { TWebModul }
  29.  
  30. constructor TWebModul.Create(AdatModule: TDataModule1);  //AdatModule is the database related unit
  31. begin
  32.   inherited Create;
  33.   FServer1 := THTTPServerThread.Create(AdatModule1.WebPort,DoHandleRequest,DoHandReqError,DoAcceptIdle);  //AdatModule1.WebPort:=8080
  34. end;
  35. {...}
  36.  
  37. //***********************************************************************************
  38.  
  39. procedure TWebModul.DoHandleRequest(Sender: TObject;  var ARequest: TFPHTTPConnectionRequest;  var AResponse: TFPHTTPConnectionResponse);
  40. var
  41.   file1: TMemoryStream;
  42. begin
  43.   file1 := TMemoryStream.Create;
  44.   {...}
  45.   if {ARequest.ContentFields.Values=} true
  46.     then
  47.       begin
  48.         fromspreadsheet(file1);  //from the spreadsheet unit
  49.  
  50.         AResponse.FreeContentStream:= true;
  51.         AResponse.ContentStream :=file1;
  52.         AResponse.ContentType:=htmlcontenttype('.html');  //:='text/html;charset=utf-8'
  53.         AResponse.Code:=200;
  54.         AResponse.SendContent;
  55.       end;
  56.   {...}
  57.   file1.Free;
  58.  
  59. end;
  60.  

egsuh

  • Hero Member
  • *****
  • Posts: 739
Re: TFPHTTPServer freezing after Edge browser request
« Reply #1 on: February 06, 2021, 02:23:39 am »
I have written webservers only those that are given as templates from Lazarus IDE, and cannot delve into your code.

Only from experience a long time ago, I remember that IE acted differently from other browsers, like Forefox or Chrome. IE creates a new instance of webserver when called from the same PC --- at that time, I used ISAPI by Delphi --- while others did not (or vice versa? not remember exactly as this is 10 years ago).

I mean, when I opened only one page of IE then it acted as expected but IE acted differently if there were other webbrowsers open and accessing the same web module (.dll file).  I checked this by accessing a global-scope variable (outside class TWebModule).

I cannot imagine exact operation for now, but these phenomena may be related with your problem.

trev

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1469
  • Former Delphi 1-7, 10.2 user
Re: TFPHTTPServer freezing after Edge browser request
« Reply #2 on: February 06, 2021, 05:26:17 am »
I mean, when I opened only one page of IE then it acted as expected but IE acted differently if there were other webbrowsers open and accessing the same web module (.dll file).

Two decades ago I used Delphi 5 (and web broker?) to create tax calculators as ISAPI DLLs for an IIS webserver. The webserver generally had 1,500 concurrent accesses during business hours and their was never an issue with the calculators or the HTML pages which they served or produced for results.
Lazarus 2.1 r65061 FPC 3.3.1 r49223 macOS 10.14.6 Xcode 11.3.1
Lazarus 2.1 r65182 FPC 3.3.1 r49223 macOS 11.4 aarch64 Xcode 12.4
Lazarus 2.1 r61574 FPC 3.3.1 r42318 FreeBSD 12.1 amd64 VMware VM
Lazarus 2.1 r61574 FPC 3.0.4 Ubuntu 20.04 Parallels VM
Lazarus 2.0.10 FPC 3.2.0 Win10 Parallels VM

egsuh

  • Hero Member
  • *****
  • Posts: 739
Re: TFPHTTPServer freezing after Edge browser request
« Reply #3 on: February 06, 2021, 07:21:57 am »
Quote
The webserver generally had 1,500 concurrent accesses during business hours and their was never an issue with the calculators or the HTML pages which they served or produced for results.

I do not say there are any problem in ISAPI web server. Mine was not a problem nor error ---- just server's different way of processing requests from IE and other browsers. Firefox and Chrome were treated as if they were coming from the same machine, but IE was as if from different source, even though all of them were running on the same PC, which allso served web server.

His web URL is localhost so I reminded that experience. Even though my hypothesis is right, I cannot figure it out right now why he is experiencing such a phenomenon. But somebody may have answers.

devEric69

  • Sr. Member
  • ****
  • Posts: 467
Re: TFPHTTPServer freezing after Edge browser request
« Reply #4 on: February 06, 2021, 12:00:37 pm »
Hello,

I don't have the answer to your problem. I use fpWeb as development framework, when it comes to write a CGI application. [off topic] But, I'm currently only using a local LAMP named XAMPP (Apache on Linux) or a local WAMP named UniServer (Apache on Windows; this binary released server is written in Pascal too). For your information, Apache hangs up as often, when it is asked for things that are more complex than normal. The tuning of web requests with Apache-CGI is very frequent.[/off topic] Nevertheless, even with a complete framework specialized in {fast}CGI, when a problem occurs, we obviously need to be able to understand the bug, so we must record the execution context. And for that, off course, we must put in place the minimum, which is amho:
- a custom exception handler for your TCGIApplication, i.e. a line like Application.OnShowRequestException:= @customExceptionHandler; .
- frame buggy code areas, with defensive calls to try..except..end; .
- return some web user informations with EHTTP.Create(...); .
- be able to retrieve, track CGI environment variables, from call to call. With such information, it's possible to manage the consistency of an Internet\Intranet user, by notifying him that your application is only compatible with such browsers (at worst), or that he should not change browsers during the progress of your wizard.

In short, it remains - first and foremost - an Application just like the others.
« Last Edit: February 06, 2021, 01:08:40 pm by devEric69 »
use: Linux 64 bits (Ubuntu 20.04 LTS).
Lazarus version: 2.0.4 (svn revision: 62502M) compiled with fpc 3.0.4 - fpDebug \ Dwarf3.

Abrax

  • New member
  • *
  • Posts: 7
Re: TFPHTTPServer freezing after Edge browser request
« Reply #5 on: April 15, 2021, 12:30:04 pm »
I found the source of the strange behavior. I should have set the FServer.Threaded:=true; in the THTTPServerThread.Create coustructor.

Code: Pascal  [Select][+][-]
  1. constructor THTTPServerThread.Create(APort: Word; const OnRequest: THTTPServerRequestHandler;
  2.   const OnRequestError : TRequestErrorHandler; const OnAcceptIdle: TNotifyEvent; OnDisconnectedByClient : TDisconnectedByClientHandler);
  3. begin
  4.   OnRequest1:=OnRequest;
  5.   OnRequestError1:=OnRequestError;
  6.   OnAcceptIdle1:=OnAcceptIdle;
  7.   OnDisconnectedByClient1 := OnDisconnectedByClient;
  8.  
  9.   FServer:=TFPHTTPServer.Create(Nil);
  10.   FServer.Port:=APort;
  11.   FServer.QueueSize:=100;
  12.   FServer.OnRequest:=OnRequest;
  13.   FServer.OnRequestError:=OnRequestError;
  14.  
  15.   //***************************//
  16.   FServer.Threaded:=true;      // <-- this is it
  17.   //***************************//
  18.  
  19.   inherited Create(False);
  20. end;

Thaddy

  • Hero Member
  • *****
  • Posts: 10783
Re: TFPHTTPServer freezing after Edge browser request
« Reply #6 on: April 15, 2021, 12:50:04 pm »
Shouldn't it be:
Code: Pascal  [Select][+][-]
  1. begin
  2.   inherited Create(False); // this should be first!
  3.   OnRequest1:=OnRequest;
  4.   OnRequestError1:=OnRequestError;
  5.   OnAcceptIdle1:=OnAcceptIdle;
  6.   OnDisconnectedByClient1 := OnDisconnectedByClient;
  7.  
  8.   FServer:=TFPHTTPServer.Create(Nil);
  9.   FServer.Port:=APort;
  10.   FServer.QueueSize:=100;
  11.   FServer.OnRequest:=OnRequest;
  12.   FServer.OnRequestError:=OnRequestError;
  13.  
  14.   //***************************//
  15.   FServer.Threaded:=true;      // <-- this is it
  16.   //***************************//
  17. end;
Reason: the inherited create may otherwise overwrite settings you passed before. Maybe not in this case, but better safe than sorry.
The reverse is true for the destructor: inherited destroy should be last if required.
« Last Edit: April 15, 2021, 12:55:08 pm by Thaddy »

devEric69

  • Sr. Member
  • ****
  • Posts: 467
Re: TFPHTTPServer freezing after Edge browser request
« Reply #7 on: April 16, 2021, 09:11:36 am »
Well done, Thaddy!
use: Linux 64 bits (Ubuntu 20.04 LTS).
Lazarus version: 2.0.4 (svn revision: 62502M) compiled with fpc 3.0.4 - fpDebug \ Dwarf3.

 

TinyPortal © 2005-2018