#1 2020-06-19 13:49:03

George
Member
Registered: 2016-04-05
Posts: 142

Webserver with custom API and file transfer

Hello!

As i remember "REST-tester" demo, client-server communication supports few protocols that work pretty good when both client and server are pascal applications.
But, what is the best way to create web server that supports:
- Non administrative privileges (not require admin account (or UAC elevation) / root)
- Multi threading
- Windows + Linux
- Custom method based API (some code that can handle request and return response with custom http headers)
- File transfer (ability to return stream data)
- http/https (https is not mandatory)
- Standalone application (no additional software, like nginx)

Where client applications are:
- Browsers (SPA)
- Other applications that can send http/https requests (not pascal based, without JavaScript support).

THttpApiServer is a way to go? Does it fit?

Last edited by George (2020-06-19 14:51:19)

Offline

#2 2020-06-19 15:32:56

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,673
Website

Re: Webserver with custom API and file transfer

THttpApiServer is Windows-only.
But in fact, you don't need to worry about the actual server used.

Just use a TSQLHttpServer class, and it would be able to use the best kind of HTTP server on the computer and the network.

Offline

#3 2020-06-19 15:37:20

George
Member
Registered: 2016-04-05
Posts: 142

Re: Webserver with custom API and file transfer

Thanks, will try.

Does TSQLHttpServer work on windows and linux as well?
And supports described above features, both for win and linux?

Last edited by George (2020-06-19 16:15:15)

Offline

#4 2020-06-19 16:27:31

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,673
Website

Re: Webserver with custom API and file transfer

Yes, it does.

Offline

#5 2020-06-26 15:50:15

George
Member
Registered: 2016-04-05
Posts: 142

Re: Webserver with custom API and file transfer

So far so good)

Can't find how to send stream data using THttpServerRequest object.
For example, to send image or font file...

I use TSQLHttpServer, with SQLHttpServer.HttpServer.OnRequest event.

Last edited by George (2020-06-26 15:53:04)

Offline

#6 2020-06-26 15:56:03

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,673
Website

Re: Webserver with custom API and file transfer

You can send a static file, using the STATICFILE_CONTENT_TYPE as header.

See how TSQLRestServerURIContext.ReturnFile is implemented.

Offline

#7 2020-06-26 16:11:01

George
Member
Registered: 2016-04-05
Posts: 142

Re: Webserver with custom API and file transfer

I saw, but i have no static files on disk.
All UI files are packed to single content file and embedded as resource.
As result, all files are available directly from memory.
Sad, that was nice idea to keep folder empty, hide files from direct access, and provide fast access without disk IO.

Maybe TSQLRestServerURIContext.ReturnBlob will help.

Last edited by George (2020-06-26 16:20:55)

Offline

#8 2020-06-26 16:43:32

mpv
Member
From: Ukraine
Registered: 2012-03-24
Posts: 1,571
Website

Re: Webserver with custom API and file transfer

@George - may be mORMotBP is do the things you need?

Last edited by mpv (2020-06-26 16:43:44)

Offline

#9 2020-06-26 16:51:05

George
Member
Registered: 2016-04-05
Posts: 142

Re: Webserver with custom API and file transfer

Based on description, yes smile
Thanks!

Offline

#10 2020-09-11 12:59:55

George
Member
Registered: 2016-04-05
Posts: 142

Re: Webserver with custom API and file transfer

Accept-Encoding is missing in Ctxt: THttpServerRequest sad
Tested with MSEdge (chromium) and Firefox.
I'm performing request to server, browser sends some request headers,
almost all headers are present in Ctxt.InHeaders, except "Connection" and "Accept-Encoding".
Is it some feature? How i can ensure that client accepts gzip?

  function RequestRouter(Ctxt: THttpServerRequest): cardinal;
  begin
    WriteLn(Ctxt.InHeaders);
    {
     Host: 127.0.0.1:8080
     Pragma: no-cache
     Cache-Control: no-cache
     DNT: 1
     Upgrade-Insecure-Requests: 1
     User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36 Edg/85.0.564.51
     Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
     Sec-Fetch-Site: cross-site
     Sec-Fetch-Mode: navigate
     Sec-Fetch-User: ?1
     Sec-Fetch-Dest: document
     Accept-Language: en-GB,en;q=0.9,en-US;q=0.8,ru;q=0.7
    }
  end;

  SQLHttpServer := TSQLHttpServer.Create('8080', [], '+', TSQLHttpServerOptions.useHttpSocket, 30 {Thread pool}, TSQLHttpServerSecurity.secNone);
  SQLHttpServer.AccessControlAllowOrigin := '*';
  SQLHttpServer.HttpServer.OnRequest := RequestRouter;

Offline

#11 2020-09-11 13:24:43

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,673
Website

Re: Webserver with custom API and file transfer

Yes, it is a feature, to reduce the memory allocation and speedup the header parsing.
Encoding and Connection headers are meant to be handled in the HTTP server itself, not in the consuming method.
For instance, gzip encoding is done in THttpServer.

You can change this default behavior via the THttpServer.HeadersNotFiltered property.

Offline

#12 2020-09-11 15:50:57

George
Member
Registered: 2016-04-05
Posts: 142

Re: Webserver with custom API and file transfer

Thanks! Exactly what i looking for smile

Offline

#13 2020-09-11 15:59:02

mpv
Member
From: Ukraine
Registered: 2012-03-24
Posts: 1,571
Website

Re: Webserver with custom API and file transfer

Yes, this is a little bit unexpected behavior - see THttpSocket.GetHeader for complete list of truncated headers in case THttpServer.HeadersNotFiltered is false (by default)

Offline

#14 2020-10-08 20:28:03

George
Member
Registered: 2016-04-05
Posts: 142

Re: Webserver with custom API and file transfer

How can i ensure that server has been started?
If i use port that already in use, i see error in debugger, but it happen outside of try except block (seems, in separate thread, some time later).
About WaitStarted, documentation says:

Ensure the HTTP server thread is actually bound to the specified port.
You should call and check this method result

But this is just a procedure, there is no result.

   try
    if Assigned(SecondHttpServer) then
     begin
      SecondHttpServer.Shutdown();
      FreeAndNil(SecondHttpServer);
     end;
    // Create new instance
    SecondHttpServer := THttpServer.Create(NewPort.ToString, nil, nil, 'LS', 30 {thread pool}, 0 {disable keep-alive}, True, True);
    SecondHttpServer.OnRequest := RequestRouter;
    SecondHttpServer.Start;
    SecondHttpServer.WaitStarted(10);
    Except
    on E: Exception do
      // Something went wrong
   end;

Last edited by George (2020-10-08 20:35:56)

Offline

Board footer

Powered by FluxBB