-
Notifications
You must be signed in to change notification settings - Fork 14
Description
Hi Antonio,
I want to deploy a Webstencils website as an ISAPI module. A standalone console app is not always the best solution. And a CGI app will 'forget' the sessions in between calls.
As an exercise I took your example and changed it into an ISAPI module. Doing so I found (and solved) a few problems.
My goal is to just replace the .dpr file without making any changes in any other file. I would like to be able to use the next version of the WebstencilsDemo without changes ;)
I do get the example working as an ISAPI module, but I needed to make some changes in your code.
I want to suggest some changes in your example.
relative paths
The main problem is about relative paths.
When you have the page
http://localhost:8081/templates
I have a URL with a longer path with the name of the .dll:
https://www.mydomain.nl/WebStencilsDemo/WebStencilsDemo_13_isapi.dll/templates
A link to the relative path /login works in your example. In the ISAPI module I get a link to
https://www.mydomain.nl/login
while I want a link to
https://www.mydomain.nl/WebStencilsDemo/WebStencilsDemo_13_isapi.dll/login
A few suggestions
1. <a href="@env.resource/customers/add"
in resources\html\customers\index.html (@env.resource is missing)
2. <form method="get" action="@env.resource/customers">
in resources\html\partials\customers\searchForm.html (@env.resource is missing)
3. <a href="@env.resource/@page.request_path"
in resources\html\partials\customers\searchForm.html (@env.resource is missing)
4. A change in Modules.Main solves a lot of problems:
else if APropName = 'resource' then AValue := request.InternalScriptName
In your example this is an empty string, for me it is /WebStencilsDemo/WebStencilsDemo_13_isapi.dll
redirect
There are (at least) three places where a redirect to relative paths occurs. In your code this can be solved in the AfterDisPatch event, like this:
procedure TMainWebModule.WebModuleAfterDispatch(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
// Message clearing - only when not redirecting
var IsRedirect := (Response.StatusCode >= 300) and (Response.StatusCode < 400);
if not (IsRedirect) and Assigned(Request.Session) then
TMessageManager.ClearMessages(Request.Session);
if IsRedirect and (Response.location[1]='/')
then Response.location := Response.HTTPRequest.ScriptName + Response.location;
end;
Both TMyWebFormsAuthenticator and TMyWebAuthorizer do redirects. Unfortunately in Web.HTTPApp this redirect is done with a call to SendRedirect. With a call to SendRedirect there is no WebModuleAfterDispatch event. So I cannot change the location there.
I don't know what would be the best solution. Maybe a kind of BaseUrl you can set in the properties? Or some code like above in the WebModuleAfterDispatch ? An AfterRedirect event ?
For now I have been able to solve this with an override of the Redirect function in the inherited TMyWebFormsAuthenticator.
function TMyWebFormsAuthenticator.Redirect(Request: TWebRequest;
Response: TWebResponse; Action: TWebAuthenticatorAction): string;
begin
result:=inherited;
if result[1]='/'
then result := Response.HTTPRequest.ScriptName + result;
end;
And the same for TMyWebAuthorizer.
I don't like this solution, because you have to change the properties of WebFormsAuthenticator in code, like this:
WebFormsAuthenticator.Free;
WebFormsAuthenticator := TMyWebFormsAuthenticator.Create(Self);
WebFormsAuthenticator.LoginURL:='/login';
WebFormsAuthenticator.LogoutURL:='/logout';
WebFormsAuthenticator.HomeURL:='/';
WebFormsAuthenticator.OnAuthenticate:=WebFormsAuthenticatorAuthenticate;
Do you see a better solution ?
BinaryPath
In an ISAPI dll Paramstr(0) gives the path to the IIS webserver. I want to have the path to the .dll.
Fortunately we can do a call to the function GetModuleName(hinstance).
On the server this path can start with '\\?\' to denote a possibly long path.
So this is my code in TMainWebModule.InitRequiredData:
BinaryPath := TPath.GetDirectoryName(GetModuleName(hinstance));
if BinaryPath.StartsWith('\\?\')
then BinaryPath:=BinaryPath.Substring(4); //remove \\?\
A small improvement
I have a couple of versions of your example. I want to see directly witch version I'm looking at. So I gave them a slightly different app_name. I want to see this in the title. This is so simple in WebStencils !
<title>@env.app_name</title> in resources\html\layouts\baseLayout.html
Thanks,
Frits.