2. URL Design
– Methods to Use Friendly URLs
by Johan Sölve
Montania System AB, Sweden
www.montania.se
3. URL Design
– Methods to Use Friendly URLs
by Johan Sölve
Montania System AB, Sweden
www.montania.se
• Software and consulting company
• Business administration solutions
for small- and medium-sized
business
10. A URL is not a Filename
• Servertotechnology file us think that a URL
makes
maps a physical
3 of 41
11. A URL is not a Filename
• Servertotechnology file us think that a URL
makes
maps a physical
• This is not how things are intended
3 of 41
12. A URL is not a Filename
• Servertotechnology file us think that a URL
makes
maps a physical
• This is not how things are intended
• A URL is a reference to a resource
3 of 41
13. A URL is not a Filename
• Servertotechnology file us think that a URL
makes
maps a physical
• This is not how things are intended
• A URL is a reference to a resource
• Disconnect the URL from the server’s file system
3 of 41
14. A URL is not a Filename
• Servertotechnology file us think that a URL
makes
maps a physical
• This is not how things are intended
• A URL is a reference to a resource
• Disconnect the URL from the server’s file system
• Design URLs!
3 of 41
15. A URL is not a Filename
• Servertotechnology file us think that a URL
makes
maps a physical
• This is not how things are intended
• A URL is a reference to a resource
• Disconnect the URL from the server’s file system
• Design URLs!
• Do URL Mapping!
3 of 41
19. Choosing URLs
• Short – easy to share
• Memorable – easy to remember
• Bookmark-able – easy to come back
4 of 41
20. Choosing URLs
• Short – easy to share
• Memorable – easy to remember
• Bookmark-able – easy to come back
• An aid in site navigation – easy to use
4 of 41
30. Choosing URLs
• Hackable – easy to navigate
• Persistent – easy to come back
• Technology Neutral – easy to grow
6 of 41
31. Choosing URLs
• Hackable – easy to navigate
• Persistent – easy to come back
• Technology Neutral – easy to grow
• The acid test
6 of 41
32. Choosing URLs
• Hackable – easy to navigate
• Persistent – easy to come back
• Technology Neutral – easy to grow
• The acid test
Can you read a URL to
someone over the phone?
6 of 41
35. URL Design
• We know how we want the URL to look
• But the a physical file requires us to map a
server technology
URL to
7 of 41
36. URL Design
• We know how we want the URL to look
• But the a physical file requires us to map a
server technology
URL to
• How can we implement URL Design?
7 of 41
37. URL Design
• We know how we want the URL to look
• But the a physical file requires us to map a
server technology
URL to
• How can we implement URL Design?
URL Mapping
7 of 41
38. URL Design
• We know how we want the URL to look
• But the a physical file requires us to map a
server technology
URL to
• How can we implement URL Design?
URL Mapping
Translate the URL to a Lasso file and parameters
7 of 41
41. URL Mapping With Lasso
• Web Server additions
‣ Apache mod_rewrite
8 of 41
42. URL Mapping With Lasso
• Web Server additions
‣ Apache mod_rewrite
‣ IISRewrite and ISAPI_Rewrite for IIS
8 of 41
43. URL Mapping With Lasso
• Web Server additions
‣ Apache mod_rewrite
‣ IISRewrite and ISAPI_Rewrite for IIS
‣ WebSTAR Rewrite
8 of 41
44. URL Mapping With Lasso
• Web Server additions
‣ Apache mod_rewrite
‣ IISRewrite and ISAPI_Rewrite for IIS
‣ WebSTAR Rewrite
+ Robust and powerful
8 of 41
45. URL Mapping With Lasso
• Web Server additions
‣ Apache mod_rewrite
‣ IISRewrite and ISAPI_Rewrite for IIS
‣ WebSTAR Rewrite
+ Robust and powerful
– Dependent on web server
8 of 41
46. URL Mapping With Lasso
• Web Server additions
‣ Apache mod_rewrite
‣ IISRewrite and ISAPI_Rewrite for IIS
‣ WebSTAR Rewrite
+ Robust and powerful
– Dependent on web server
Completely outside of Lasso – split logic, more to
learn
8 of 41
50. URL Mapping With Lasso
• mod_rewrite example
RewriteEngine On
#RewriteBase /
# Check to see if the request is a real file or directory
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !.*/Security
# Everything else gets sent to index.lasso
RewriteRule ^(.*)$ /index.lasso?response_filepath=/$1 [QSA,L,NS]
9 of 41
51. URL Mapping With Lasso
• mod_rewrite example
RewriteEngine On
#RewriteBase /
# Check to see if the request is a real file or directory
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !.*/Security
# Everything else gets sent to index.lasso
RewriteRule ^(.*)$ /index.lasso?response_filepath=/$1 [QSA,L,NS]
mod_rewrite can take a bit of black
magic to master
9 of 41
54. URL Mapping With Lasso
• Lasso Built-In using error.lasso
10 of 41
55. URL Mapping With Lasso
• Lasso Built-In using error.lasso
Use a custom error.lasso page to trap requests
for non-existent files
10 of 41
56. URL Mapping With Lasso
• Lasso Built-In using error.lasso
Use a custom error.lasso page to trap requests
for non-existent files
error.lasso
10 of 41
59. URL Mapping With Lasso
• Lasso Built-In using [Define_AtBegin]
11 of 41
60. URL Mapping With Lasso
• Lasso Built-In using [Define_AtBegin]
http://reference.omnipilot.com/LDML8Reference.LassoApp?tag=6564
prior to processing any code in the current page.
11 of 41
62. Define_Atbegin as URL
processor
• Defines code that will be executed before each
page on a site is loaded or executed
12 of 41
63. Define_Atbegin as URL
processor
• Defines code that will be executed before each
page on a site is loaded or executed
• Look at the requested URL and map it toany
a
Lasso file and parameters before loading
page for it
12 of 41
66. Advantages with AtBegin
• Mostly self-contained within Lasso
• More portable, less things to setup
13 of 41
67. Advantages with AtBegin
• Mostly self-contained within Lasso
• More portable, less things to setup
• All logic kept within Lasso
13 of 41
68. Advantages with AtBegin
• Mostly self-contained within Lasso
• More portable, less things to setup
• All logic kept within Lasso
• Logic can be integrated with rest of site and
database
13 of 41
70. How Does it Work?
Visitor
http://www.myweather.com/halmstad/weekend.lasso
Web Server
/halmstad/
Lasso weekend.las
so
Normal processing
14 of 41
71. How Does it Work?
Visitor
Visitor
http://www.myweather.com/halmstad/weekend.lasso
http://www.myweather.com/halmstad/weekend
Web Server
/halmstad/
Lasso weekend.las
so
Web Server
Lasso
urlhandler_ urlhandler.
index.lasso
atbegin.lasso inc
AtBegin processing
14 of 41
74. Web Server Configuration
• Needed to allow URLs without .lasso (optional)
• Apache config
<LocationMatch quot;^[^.]+$quot;>
# anywhere without file extensions
SetHandler lasso8-handler
</LocationMatch>
15 of 41
75. Web Server Configuration
• Needed to allow URLs without .lasso (optional)
• Apache config
<LocationMatch quot;^[^.]+$quot;>
# anywhere without file extensions
SetHandler lasso8-handler
</LocationMatch>
• IIS 6.0 on Windows 2003 Server
15 of 41
76. Web Server Configuration
• Needed to allow URLs without .lasso (optional)
• Apache config
<LocationMatch quot;^[^.]+$quot;>
# anywhere without file extensions
SetHandler lasso8-handler
</LocationMatch>
• IIS 6.0 on Windows 2003 Server
Wildcard Application Mapping to send requests to
Lasso on a folder-by-folder basis
15 of 41
79. Lasso Configuration
• Define_AtBegin or globally LassoStartup either
must be in
for a Lasso Site
urlhandler_atbegin.lasso
<?LassoScript
Define_AtBegin: {
if: file_exists: '/urlhandler.inc';
include: '/urlhandler.inc';
/if;
};
16 of 41
80. Lasso Configuration
• Define_AtBegin must bedefinesLassoScript that either
{ } in LassoStartup
a Compund
Expression, a
for a Lasso Site or globally in a variable and
can be stored
urlhandler_atbegin.lasso executed later.
<?LassoScript
Define_AtBegin: {
if: file_exists: '/urlhandler.inc';
include: '/urlhandler.inc';
/if;
};
16 of 41
81. Lasso Configuration
• Define_AtBegin or globally LassoStartup either
must be in
for a Lasso Site
urlhandler_atbegin.lasso
<?LassoScript
Define_AtBegin: {
if: file_exists: '/urlhandler.inc';
include: '/urlhandler.inc';
/if;
};
We want to keep this as generic and transparent as
possible
16 of 41
82. Lasso Configuration
• Define_AtBegin or globally LassoStartup either
must be in
for a Lasso Site
urlhandler_atbegin.lasso
<?LassoScript
Define_AtBegin: {
if: file_exists: '/urlhandler.inc';
include: '/urlhandler.inc';
/if;
};
We want to keep this as generic and transparent as
possible
If urlhandler.inc is not present in a virtual host,
everything works normally
16 of 41
84. The URL Handler
• All Lasso requests are passing through one single
spot
17 of 41
85. The URL Handler
• All Lasso requests are passing through one single
spot
• Parse the requested URL by looking at
[response_filepath]
17 of 41
86. The URL Handler
• All Lasso requests are passing through one single
spot
• Parse the requested URL by looking at
[response_filepath]
• Send the result of the parsing to the actual Lasso
file by setting variables
17 of 41
89. The URL Handler
• ExampleofURL handler for a News and Products
section a site
18 of 41
90. The URL Handler
• ExampleofURL handler for a News and Products
section a site
urlhandler.inc
<?LassoScript
// this file is called by the atbegin handler, so it is executed
// before any page is being processed.
if: response_filepath -> (endswith: '.lasso') || response_filepath ->
(endswith: '.lassoapp');
// don't do anything for normal .lasso and .lassoapp requests
else;
if: response_filepath -> (beginswith: '/news/')
|| response_filepath -> (beginswith: '/products/');
var: 'url_path'=response_filepath,
'section'='';
$url_path -> (removeleading: '/');
18 of 41
91. The URL Handler
• ExampleofURL handler for a News and Products
section a site
if: !($url_path -> endswith: '/');
$url_path += '/';
/if;
if: $url_path -> (beginswith: 'news/');
// check for pattern /news/2004/12/31/keyword/
//using regular expression
var: 'pathcheck'=(string_findregexp: $url_path,
-find='^news/(20d{2})/(0[1-9]|1[0-2])/'
+ '([^/]+)/([^/]*)');
if: $pathcheck -> size >= 5;
$section = 'news';
var: 'newsdate'=($pathcheck -> (get: 2))
+ '/' + ($pathcheck -> (get: 3))
+ '/' + ($pathcheck -> (get: 4)); 18 of 41
92. The URL Handler
• ExampleofURL handler for a News and Products
section a site
$newsdate = (date: $newsdate, -format='%Y/%m/%d');
var: 'newskeyword'=($pathcheck -> (get: 5)),
var: 'newsextra'='';
if: $pathcheck -> size >= 6;
$newsextra=($pathcheck -> (get: 6));
/if;
/if;
else: $url_path -> beginswith: 'products/';
$section = 'products';
// split up the path in components
$url_path = $url_path -> (split: '/');
/if;
18 of 41
93. The URL Handler
• ExampleofURL handler for a News and Products
section a site
// run site
// use absolute path!
$__HTML_REPLY__ = include: '/index.lasso';
abort;
/if;
/if;
?>
18 of 41
97. The URL Handler
• index.lasso now has these variables:
$url_path
19 of 41
98. The URL Handler
• index.lasso now has these variables:
$url_path
$section tells the site what main section we are in.
19 of 41
99. The URL Handler
• index.lasso now has these variables:
$url_path
$section tells the site what main section we are in.
• For the news section also these variables
19 of 41
100. The URL Handler
• index.lasso now has these variables:
$url_path
$section tells the site what main section we are in.
• For the news section also these variables
$newsdate publication date, used when getting the news article from database
19 of 41
101. The URL Handler
• index.lasso now has these variables:
$url_path
$section tells the site what main section we are in.
• For the news section also these variables
$newsdate publication date, used when getting the news article from database
$newskeyword an identification string for the news article
19 of 41
102. The URL Handler
• index.lasso now has these variables:
$url_path
$section tells the site what main section we are in.
• For the news section also these variables
$newsdate publication date, used when getting the news article from database
$newskeyword an identification string for the news article
$newsextra optional extra item, for example ‘comments’
Try it
19 of 41
104. Running The Site
• [Define_AtBegin] will never output anything to
the web page by itself
20 of 41
105. Running The Site
• [Define_AtBegin] will never output anything to
the web page by itself
• Explicitly put the output to the page buffer
20 of 41
106. Running The Site
• [Define_AtBegin] will never output anything to
the web page by itself
• Explicitly put the output to the page buffer
• [abort] so Lasso doesn’t try to run the
requested file again afterwards
20 of 41
107. Running The Site
• [Define_AtBegin] will never output anything to
the web page by itself
• Explicitly put the output to the page buffer
• [abort] so Lasso doesn’t try to run the
requested file again afterwards
$__HTML_REPLY__ = include: '/index.lasso';
abort;
20 of 41
109. Error Handling
• The requested URL is not a physical file so a File
Not Found can technically not happen
21 of 41
110. Error Handling
• The requested URL is not a physical file so a File
Not Found can technically not happen
• For invalid URLs a be provided status code and
proper HTTP
error page should
21 of 41
111. Error Handling
• The requested URL is not a physical file so a File
Not Found can technically not happen
• For invalid URLs a be provided status code and
proper HTTP
error page should
• Invalid URL: 404 Not Found
21 of 41
112. Error Handling
• The requested URL is not a physical file so a File
Not Found can technically not happen
• For invalid URLs a be provided status code and
proper HTTP
error page should
• Invalid URL: 404 Not Found
• URL no longer available: 410 Gone
21 of 41
113. Error Handling
• The requested URL is not a physical file so a File
Not Found can technically not happen
• For invalid URLs a be provided status code and
proper HTTP
error page should
• Invalid URL: 404 Not Found
• URL no longer available: 410 Gone
• See http://www.w3.org/Protocols/HTTP/1.1/
spec.html#Status-Codes
21 of 41
117. Error Handling
• Custom tag to set HTTP status
http://tagswap.net/setHTTPstatus
define_tag: 'setHTTPstatus', -required='statuscode';
// replace status code but keep leading HTTP with version
$__http_header__ = (string_replaceregexp: $__http_header__,
-find='(^HTTPS+)s+.*?rn',
-replace='1 ' + #statuscode + 'rn');
/define_tag;
setHTTPstatus: '404 Not Found';
22 of 41
119. Watch Out
• Important to debugthe site might fail. every
carefully. Otherwise
page requested on
23 of 41
120. Watch Out
• Important to debugthe site might fail. every
carefully. Otherwise
page requested on
• Can’t use abort as debug method – nothing at all
will output
23 of 41
131. Virtual Host Handling
• Look at the ‘host’ field in the request header
• Direct the request to the site’s folder
25 of 41
132. Virtual Host Handling
• Look at the ‘host’ field in the request header
• Direct the request to the site’s folder
- Not for images and other external files
25 of 41
133. Virtual Host Handling
• Look at the ‘host’ field in the request header
• Direct the request to the site’s folder
- Not for images and other external files
- Must use relative paths for includes
25 of 41
138. Debugging
• If you suspectitthat a page makes Lasso to crash
but can’t find
27 of 41
139. Debugging
• If you suspectitthat a page makes Lasso to crash
but can’t find
• Log the page request to a database in AtBegin
27 of 41
140. Debugging
• If you suspectitthat a page makes Lasso to crash
but can’t find
• Log the page request to a database in AtBegin
• Remove the log entry in AtEnd
27 of 41
141. Debugging
• If you suspectitthat a page makes Lasso to crash
but can’t find
• Log the page request to a database in AtBegin
• Remove the log entry in AtEnd
• Leftover entries are pages that have crashed
Credit goes to Bil Corry for this idea
27 of 41
153. Protected Downloads
• Set Lasso to process the download file type
• AtBegin handler authorizes the download
request
31 of 41
154. Protected Downloads
• Set Lasso to process the download file type
• AtBegin handler authorizes the download
request
• If request is ok, use file_stream to serve the
requested file
31 of 41
156. Protection of .inc Files
• Make .inc files processed by Lasso in Web server
32 of 41
157. Protection of .inc Files
• Make .inc files processed by Lasso in Web server
<?LassoScript
define_atbegin({
if: response_filepath -> (endswith: '.inc');
$__HTML_REPLY__ = '<h1>Not authorized</h1>';
// set proper result code too
abort;
/if;
} );
?>
32 of 41
159. Locking down
SiteAdmin.LassoApp
• To make from SiteAdmin.LassoApp can only be
sure
reached the server machine
33 of 41
160. Locking down
SiteAdmin.LassoApp
• To make from SiteAdmin.LassoApp can only be
sure
reached the server machine
<?LassoScript
define_atbegin({
if: response_filepath -> split: '/' -> last
-> (beginswith: 'siteadmin.')
&& response_filepath -> (endswith: '.lassoapp')
&& client_ip != '127.0.0.1';
$__HTML_REPLY__ = '<h1>Not authorized</h1>';
// set proper result code too
abort;
/if;
} );
?>
33 of 41
163. URL Design
• Disconnect the URL from the server’s file
system
• AtBegin lets us do URL mapping all within Lasso
34 of 41
164. URL Design
• Disconnect the URL from the server’s file
system
• AtBegin lets us do URL mapping all within Lasso
• AtBegin has many other interesting uses
34 of 41