While building Web sites/application, you're bound to come across issues with regard to "paths". Sometimes these paths are related to URLs and sometime these "paths" are related to physical paths to images or html templates on your web server. In this article we'll see how to tackle some of these issues.
Relative Paths
These are the primarily URLs that seem to be in short form or a partial URL in HTML. For example, lets take the <img> tag. The <img> tag has an attribute called src. The value of this attribute needs to be the URL where the image can be found. Lets experiment a bit. We'll build a very simple html page:
The Simple HTML File for testing.
<html>
<head>
<title>Experimenting with Relative Paths</title>
</head>
<body>
<img src="http://www.matlus.com/images/MatlusTabs_Base.png" border="0" />
</body>
</html>
I assume you create this page using notepad and save it as RelativePaths.htm. Now open this file in your browser by double clicking on the file. You should see an image in there. This image is downloaded from my web site. That was pretty obvious since the src attribute contains the full URL to that image. When you're building web sites/applications you don't want to hard code the complete URL to your images in the src attribute. This is because you may re-use your code/templates for another site or application or the domain name changes etc. So ideally you want to use a URL of the form <img src="/images/MatlusTabs_Base.png" border="0" />
The src attribute is in the form of a relative path. If you navigate to my web site, and take a look at some of the html there, you'll notice that the src attribute of the <img> tags do not contain the domain name as it did earlier. But you still see the images. Now modify the <img> tag in the html page you made earlier to be like that shown above. You'll notice that you don't see an image any more.
I'd like to explain this in terms of how a web browser works. When a browser is pointed to an html page, it retrieves this html page. First all it does is it gets the html (this is what you see when you do a "view source menu option"). It then parses this html. While parsing the html it comes across the <img> tag. It looks at the src attribute. What? No domain? Ok, then I'll just assume the domain is the same domain that the html came from (It resolves the relative path)! But there is no image in this path.
Difference between opening an HTML page by double clicking it and "browsing" to it.
If you double clicked on the html file (the physical file), the browser looks for the image in this case in a sub folder of the folder in which the html file resides. If you have a web server running locally and called this html file using a url such as
http://localhost/test.htm then when the browser makes a request on the web server for the image, it expects to find an image in a subfolder (or virtual folder).
This applies to other tags that may use relative paths as well, such as the <link> tag's href attribute, or an <a> tag's href attribute. For tags that have attributes such as the href attribute, the browser actually makes additional requests on the web server (one additional request for tag with such an attribute). In the first go, it only retrieves the HTML. This is important to know, since it effects the speed and scalability of the systems you build.
You will have noticed relative paths that include the ISAPI dll or CGI exe file name as well. In code, you use the Request.ScriptName property. This results in something like /scripts/myisapi.dll. In this case, you don't want to hard code the name of the application either. It's best using Request.ScriptName. But again, a relative path only makes sense if the ISAPI (in this case) is in the same domain as the web page that uses this relative path.
Virtual folders and the TPageProducer
The "images" part of the url for the image we've been using is a virtual folder. This folder can be one of two things:
- A sub folder of your Web Server's root folder. (C:\inetpub\wwwroot\images in case of IIS)
- A virtual folder defined in your web server for the web site. This virtual folder has the name "images" but it could be virtually anywhere on the server's hard disk. A network share or an URL.

When creating a virtual folder in IIS, make sure the User name is in the form MACHINENAME\UserName where MACHINENAME is the name of the machine on the network on which the physical folder exists. Just UserName will not work.
If in your environment your development machine's directory structure does not match that of the target production machine, you should create virtual folders on your development machine (and also production machine if need be) that map to the target machine. Never hard code paths in the html that is returned to the browser. Following this rule will go a long way in smoothening out the deployment process while also allowing for changes later, in the production environment.
In Delphi we have this wonderful component called the TPageProducer. We won't go into the details of how to use it here. However, it has a property called HTMLFile. The value of this property is normally the path and name of an html template (a file that has special tags that the Page Producer understands). Now the PageProducer, needs a physical path (not URL) for the physical .htm file. The IUSR_ user needs to have read access to this folder and file.
Lets say you've defined a virtual folder called HTMLTemplates in your WebServer. This virtual folder points to a physical location on your hard drive. You can get the physical path of the virtual folder by using the Request object's TranslateURI method.
If you leave the parameter (to the TranslateURI method) empty, you'll get the physical path to the root folder of your web server (C:\Inetpub\wwwroot in the case of IIS). If you supply '/images' as the parameter you'll get the physical path of the "images" virtual folder. If no such folder exists (that is a virtual folder has not been defined), you'll simply get the word "\images" appended to the web server's root folder path (notice the way the forward slash changes to a back slash for physical paths).
Given this knowledge, you should be able to get your page producer to load an html template from any folder on your web server . Simple code like that shown below works really well and can be used in all your ISAPIs if you follow a trend.
One way of implementing Mapping of Virtual Paths to Physical Paths
TWebModule1 = class(TWebModule)
procedure WebModuleBeforeDispatch(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
private
FHTMLTemplatePath: string;
property HTMLTemplatePath: string read FHTMLTemplatePath;
{ Private declarations }
public
{ Public declarations }
end;
var
WebModule1: TWebModule1;
implementation
{$R *.DFM}
procedure TWebModule1.WebModuleBeforeDispatch(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
if HTMLTemplatePath = '' then
FHTMLTemplatePath := Format('%s\',[Request.TranslateURI('/HTMLTemplates')]);
end;
It is assumed here that either you've defined a virtual folder in your web server called HTMLTemplates, or you've got a physical folder under your web server's root folder by this name.
Further, the "scripts" folder generally has "read/execute" access. It is not advisable to keep your html templates in this "kind" of folder. Under W2K, sub folders of this folder automatically inherit the parent folder's property. My advice is that you create a sub folder under your web server's root folder (they will automatically have the correct access rights), or create a folder under inetpub and map a virtual folder to it.