You are not logged in.
Pages: 1
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
Apologies for my english and thanks in advance.
Esteban
Esteban
Offline
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
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
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
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
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
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
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
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
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
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
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
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
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
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.
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
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
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.
But it is always better to not call the API at all.
Offline
For the record, "[mormot_root]\SQLite3\Samples\04 - HTTP Client-Server\Unit2Static.pas" is the file that demonstrate EMartin's idea
Thank you two.
Delphi XE4 Pro on Windows 7 64bit.
Lazarus trunk built with fpcupdelux on Windows with cross-compile for Linux 64bit.
Offline
Pages: 1