You are not logged in.
Pages: 1
Is it possible to serve files/resources that are compiled into the executable?
I am busy creating a bunch of javascript files which will be used to access the interfaces defined in the mormot service. Ideally I would like these files to be accessible similar to http://mormotserver:888/root/files/usermanagement.js. But I do not want them in a folder on the disk where anyone can edit them and claim I provided them in a different state than I did. Having them compiled in as a resource also ensures that these files are always at the same version as the rest of the executable.
I use mormot authentication and they would have to be available to unauthenticated users, since the login pages will need them.
Does anybody have any practical ideas or pointers on how to achieve this?
Offline
You could simply use ResourceToRawByteString or ResourceSynLZToRawByteString functions to retrieve the content as a blob, ready to be sent back to the client.
The easiest is to define a method-based service named "Files", like this:
procedure TMyRestServer.Files(Ctxt: TSQLRestServerURIContext);
var fn: TFileName;
blob: RawByteString;
begin
if Ctxt.Method<>mGet then
exit;
UTF8ToString(Ctxt.URIBlobFieldName,fn);
ResourceToRawByteString(fn,PChar(10),blob);
if blob<>'' then
Ctxt.ReturnBlob(blob,200,true,fn) else
Ctxt.Error('',HTML_NOTFOUND);
end;
Note that the resource name should contain the file name extension (.js) to return the expected mime type.
Offline
Thanks, this looks exactly like what I need. Were there any recent changes to UTF8ToString and ReturnBlob? The compiler doesn't expect the fn parameter as well in these 2 functions.
Offline
Just committed as http://synopse.info/fossil/info/cbf63374107690
Offline
This is excellent! Works like a dream! Thanks ab!
For future users, resource names are not allowed to contain a fullstop . So I name the resources the same as the filename, but just exclude the fullstop in the resource name. Then when loading the resource, instead of the filename, I use:
ResourceToRawByteString(ReplaceStr(fn, '.', ''), PChar(10), blob);
and leave the rest as-is.
Last edited by squirrel (2015-10-08 12:41:42)
Offline
I can't see a difference between sending a js from an exe or from a file-system on the server.
In both cases the user could change the file on the client.
Offline
@daniel: I fully agree about client side, opening firebug and making changes to loaded code is childsplay. But the issue here is server side when you distribute software to sites that you do not administer yourself. In this scenario, you want the js files to always be at the same version as the exe (updated together) and not give the local site admins the option to permanently change the js files on server side to impact an sla.
Admins are supposed to be the responsible ones, but that does not change reality. When you deal with partial upgrades or custom changes done by someone else's admins and it impacts your application's stability, you want to package as much together as possible.
Offline
@ab: The method based service you provided works perfectly and I am currently using it to serve .js files without issue. I currently use ServiceMethodByPassAuthentication to ensure these files can be served before log in.
I now need to be able to serve some files only to authenticated users. I tried 2 approaches without success and would be very happy if you can give some advice.
First I copied the working method above, gave it a new name and then didn't bypass authentication for it. Requests to this method always results in 403 Forbidden.
Secondly as an alternative, I added it to one of my interfaces (which I prefer since it keeps related code together). But I'm not sure how to impliment it / what the return type must be. This just always returns {"result":[]}
Offline
To have an interface-based service method return any content, see http://synopse.info/files/html/Synopse% … #TITLE_447
You could use the very same method-based service, and use the Ctxt.Session* properties to check if the user is currently authenticated.
Offline
@ab Would it be possible to use this method to serve files without explicitly calling the Files function? Similarly, is it possible to have an empty root?
So that for example this url: http://localhost:8080/root/files/myfile.html
would become: http://localhost:8080/myfile.html
I assume that one way of using the files method as default would be to register it as an error handler for Error 400s, which would allow me to use custom pages for errors such as 500, 404 etc
Any advice?
Offline
Thanks, that sounds exactly like what I need, but I'm not sure how to make it work. The server runs locally on an intranet server called demoserver on port 8080.
Without redirecting, I am able to access a file using either http://localhost:8080/root/files/login.html or http://demoserver:8080/root/files/login.html
These same urls still work with redirecting, but the Ctxt.URIBlobFieldname changes to include the root/files/ which it didn't before
However, even with redirection, I am unable to access the files function using http://localhost:8080/login.html
It doesnt enter the files method and returns a 503 Service Unavailable error
Using the documentation, I tried all of the following
aHttpServer.DomainHostRedirect('localhost', 'root/files');
aHttpServer.DomainHostRedirect('localhost:8080', 'root/files');
aHttpServer.DomainHostRedirect('demoserver', 'root/files');
aHttpServer.DomainHostRedirect('demoserver:8080', 'root/files');
using
aHttpServer.RootRedirectToURI('root/files');
causes a visit to http://localhost:8080/login.html to give a 404 error (not generated by mormot) while visiting http://localhost:8080/root/files/login.html still works
Additional info: My model and server is created using
aModel := TSQLModel.Create([],'root');
aHttpServer := TSQLHttpServer.Create(IntToStr(8080), [aRestServer],'+',useHttpApiRegisteringURI)
Last edited by squirrel (2016-01-28 10:32:43)
Offline
Am I doing something wrong?
Offline
On the HTTP API level your server is listening on `http://localhost:8080/root` (you pass a `root` during call to TSQLModel.Create), so URL http://localhost:8080/ do not handled by mORMot at all. Only requests to http://localhost:8080/root/* are handled by mORMot
Last edited by mpv (2016-02-10 14:51:40)
Offline
Pages: 1