#1 2013-01-17 15:25:54

EMartin
Member
From: Buenos Aires - Argentina
Registered: 2013-01-09
Posts: 332

Using TSQLHttpServer with RESTFull/Web Server

Hi,

   I am newbie with this great framework. My problem is that I want to use TSQLHttpServer for serving web pages and make use of the mORMot REST protocol. How I can implement the TSQLHttpServer serving web pages as well as REST protocol ? My idea is make with mORMot a full web server (not IIS/Apache). Any example will be wonderful smile

   Apologies for my english and thanks in advance.

Esteban


Esteban

Offline

#2 2013-01-17 15:31:09

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

Re: Using TSQLHttpServer with RESTFull/Web Server

See this thread for ajax auth: http://synopse.info/forum/viewtopic.php?id=490
For simple (very simple) web server implementation see "\SQLite3\Samples\09 - HttpApi web server" example.

Offline

#3 2013-01-17 15:49:20

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 13,048
Website

Re: Using TSQLHttpServer with RESTFull/Web Server

Yes.

You can see:
  http://synopse.info/fossil/dir?name=SQL … web+server
and
  http://synopse.info/fossil/dir?name=SQL … SQL+server

But REST routing itself is made in mORMot.pas, i.e. with services.
For direct REST services, see method-based services.
http://blog.synopse.info/post/2010/07/1 … phi-7-2010

Offline

#4 2013-01-17 15:53:36

EMartin
Member
From: Buenos Aires - Argentina
Registered: 2013-01-09
Posts: 332

Re: Using TSQLHttpServer with RESTFull/Web Server

I have saw to both. I make with sample 09 serve a web page, but  I don't know how invoke REST JSON from a web client against a THttpApiServer ? This server not process REST request and TSQLHttpServer yes.

Thanks.


Esteban

Offline

#5 2013-01-17 16:12:37

EMartin
Member
From: Buenos Aires - Argentina
Registered: 2013-01-09
Posts: 332

Re: Using TSQLHttpServer with RESTFull/Web Server

Ok, I will rephrase my question. How, with a THttpSQLServer, I can serve a web page, that is, ie. an index.html ?

I tried this but the request never reach the OnRequest event that I implemented, only the first time.

Thanks.

PD: excellent framework and much better forum.


Esteban

Offline

#6 2013-01-17 16:18:11

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 13,048
Website

Re: Using TSQLHttpServer with RESTFull/Web Server

http://synopse.info/fossil/finfo?name=S … Server.dpr does it: it create an HTML directory file, or send back directly a file to the client.

Offline

#7 2013-01-17 16:32:26

EMartin
Member
From: Buenos Aires - Argentina
Registered: 2013-01-09
Posts: 332

Re: Using TSQLHttpServer with RESTFull/Web Server

Yes, I did with this example to serve a file index.html, but after that I need request data through REST JSON, but THttpApiServer has not implemented the RESTFul JSON logic that has TSQLHttpServer. That is, TSQLHttpServer.Request method manage the GET/PUT/DELETE/etc. but not static files and THttpApiServer manage static files but not GET/PUT/DELETE/etc.

Thank.


Esteban

Offline

#8 2013-01-17 16:47:17

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 13,048
Website

Re: Using TSQLHttpServer with RESTFull/Web Server

The http://blog.synopse.info/post/2010/07/1 … phi-7-2010 defines how you can return a BLOB content, or if Content-Type response is set to HTTP_RESP_STATICFILE, a static file.

Something like that:

Ctxt^.Call.OutHead := HEADER_CONTENT_TYPE+GetMimeContentType(pointer(Call.OutBody),Length(Call.OutBody));
Ctxt^.Call.OutStatus := HTML_SUCCESS; // 200 OK

Offline

#9 2013-01-17 20:34:53

EMartin
Member
From: Buenos Aires - Argentina
Registered: 2013-01-09
Posts: 332

Re: Using TSQLHttpServer with RESTFull/Web Server

Ok, I did it works, but I am in the same point that with THttpApiServer, the referenced files inside web page (.css, .js, etc.) are not processed, that is, not sent to client browser and the displayed page is incomplete. Any other ideas ?

The other hand, I tried to use interfaced services but access violation in RecordClear function before invoke the implemented function service, sure I am missing something.

Thanks.


Esteban

Offline

#10 2013-01-17 20:40:53

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 13,048
Website

Re: Using TSQLHttpServer with RESTFull/Web Server

Without code to reproduce the issue or at least the stack trace and context, this is impossible to find out what is wrong...

Offline

#11 2013-01-17 21:44:32

EMartin
Member
From: Buenos Aires - Argentina
Registered: 2013-01-09
Posts: 332

Re: Using TSQLHttpServer with RESTFull/Web Server

Interface based services or method based services used to return web pages and supplementary files inside the page is not my preferred method of web server. For example this is the URL used for get a page:

http://localhost:888/service/GetFile?F=html\TVWebChat.html

How can I get the referenced files inside the page ? For example:

<script src="js/jquery-1.8.3.min.js" type="text/javascript"></script>

This is I need, the exception of the interface based services is not a problem, I know that it works with normal purposes.

I tried Delphi On Rails (another nice framework) but mORMot has much more features.

Summarizing, how I do a TSQLRestServer serving static files and to use interface based services from a web client (I am using JQuery) ?


Esteban

Offline

#12 2013-01-18 06:24:40

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 13,048
Website

Re: Using TSQLHttpServer with RESTFull/Web Server

You are not obliged to use parameters.
The method name can be used.

You can for instance create a method named "js" and it will be executed for every http://ip/root/js/.... calls, then you can send back the file.
Something like this (not tested):

procedure TSQLRestMyServer.Js(var Ctxt: TSQLRestServerCallBackParams);
var FileName: RawUTF8;
begin
  // here Ctxt.URIWithoutSignature='root/js/jquery-1.8.3.min.js'
  FileName := 'c:\serverroot\'+copy(Ctxt.URIWithoutSignature,9,200); // 'c:\serverroot\jquery-1.8.3.min.js'
  Ctxt.Returns(FileName,HTML_SUCCESS,HEADER_CONTENT_TYPE+HTTP_RESP_STATICFILE);
end;

Offline

#13 2013-01-18 10:28:52

EMartin
Member
From: Buenos Aires - Argentina
Registered: 2013-01-09
Posts: 332

Re: Using TSQLHttpServer with RESTFull/Web Server

I solved the problem with a more simple modification, not the ideal (I touched mORMot source code) but it works perfectly. I modified in mORMotHttpServer.pas.TSQLHttpServer.Request adding the directive virtual. Then I implemented a custom class:

  TSQLHttpServerWeb = class(TSQLHttpServer)
  protected
    function Request(const InURL, InMethod, InHeaders, InContent, InContentType: RawByteString;
      out OutContent, OutContentType, OutCustomHeader: RawByteString): cardinal; override;
  end;

...

function TSQLHttpServerWeb.Request(const InURL, InMethod, InHeaders, InContent,
  InContentType: RawByteString; out OutContent, OutContentType,
  OutCustomHeader: RawByteString): cardinal;
var
  FileName: TFileName;
  FN, lPath: RawUTF8;
begin
  if not IdemPChar(pointer(InURL),'/W') then // W is the root
  begin
    result := 404;
    exit;
  end;
  lPath := StringReplaceChars(UrlDecode(copy(InURL, 1, 3)),'/','\');
  while (lPath <> '') and (lPath[1]='\') do
    Delete(lPath, 1, 1);
  FN := StringReplaceChars(UrlDecode(copy(InURL,4,maxInt)),'/','\');
  while (FN<>'') and (FN[1]='\') do
    delete(FN,1,1);
  while (FN<>'') and (FN[length(FN)]='\') do
    delete(FN,length(FN),1);
  FileName := UTF8ToString(FN);
  if FileExists(FileName) then
  begin
    OutContent := StringToUTF8(FileName);
    OutContentType := HTTP_RESP_STATICFILE;
    result := HTML_SUCCESS; // THttpApiServer.Execute will return 404 if not found
  end
  else
    inherited; // invoke the TSQLHttpServer.Request for services.
end;

Now, I will implement services using interfaces for retrieve/update data that will be invoked from client web page through REST.

Thank you very much for your quick answers.


Esteban

Offline

#14 2013-01-18 13:28:05

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 13,048
Website

Re: Using TSQLHttpServer with RESTFull/Web Server

This is a nice solution.

I've declared TSQLHttpServer.Request method as virtual, to allow easiest, like direct file sending to the clients.
See http://synopse.info/fossil/info/cf89e5be3a
This is a good idea.

I want to do some refactoring at TSQLHttpServer level, to include HTTP server 2.0 API, in particular.

Be warned that FileExists() can be slow, since it calls slow Windows API.
Having an in-memory hashed list of files, sounds like a better idea, about performance.

Offline

#15 2013-01-18 13:34:11

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

Re: Using TSQLHttpServer with RESTFull/Web Server

There is no need to check FileExists(FileName)  at all. If file not exist HTTPAPI send 404 automatically.

Offline

#16 2013-01-18 15:24:19

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 13,048
Website

Re: Using TSQLHttpServer with RESTFull/Web Server

mpv wrote:

There is no need to check FileExists(FileName)  at all. If file not exist HTTPAPI send 404 automatically.

Here FileExists() is used to guess if the server is to serve a file or ask the RESTful services.

I suppose a simple extension check may be enough: if the URI is finishing with .html/.png/.css/.js/.jpg it can be considered as a file request, otherwise the inherited method is to be called.

Offline

#17 2013-01-18 16:52:04

EMartin
Member
From: Buenos Aires - Argentina
Registered: 2013-01-09
Posts: 332

Re: Using TSQLHttpServer with RESTFull/Web Server

Administrator wrote:

I've declared TSQLHttpServer.Request method as virtual, to allow easiest, like direct file sending to the clients.
See http://synopse.info/fossil/info/cf89e5be3a
This is a good idea.

Excellent, I'll update that revision.

Administrator wrote:

Be warned that FileExists() can be slow, since it calls slow Windows API.
Having an in-memory hashed list of files, sounds like a better idea, about performance.

I know, I'll use GetAttributesEx API Windows initially and then I'll use a hashed list.

Thanks for all.


Esteban

Offline

#18 2013-01-25 15:30:45

Junior/RO
Member
Registered: 2011-05-13
Posts: 201

Re: Using TSQLHttpServer with RESTFull/Web Server

I allways use JclFileUtils.FileExists(), this function was implemented using a GetFileAttributes call. It is a better approach than SysUtils.FileExists() which use FindFirst/FindNext API.

Offline

#19 2013-01-25 18:16:55

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 13,048
Website

Re: Using TSQLHttpServer with RESTFull/Web Server

Junior/RO wrote:

I allways use JclFileUtils.FileExists(), this function was implemented using a GetFileAttributes call. It is a better approach than SysUtils.FileExists() which use FindFirst/FindNext API.

Our enhanced RTL code for Delphi 7/2007 does the same.
wink

But it is always better to not call the API at all.

Offline

#20 2017-02-07 04:38:07

edwinsn
Member
Registered: 2010-07-02
Posts: 1,166

Re: Using TSQLHttpServer with RESTFull/Web Server

For the record, "[mormot_root]\SQLite3\Samples\04 - HTTP Client-Server\Unit2Static.pas" is the file that demonstrate EMartin's idea smile

Thank you two.


Delphi XE4 Pro on Windows 7 64bit.
Lazarus trunk built with fpcupdelux on Windows with cross-compile for Linux 64bit.

Offline

Board footer

Powered by FluxBB