Using URL Rewrite with QDIG
One of the applications that I like to use on my websites it the Quick Digital Image Gallery (QDIG), which is a simple PHP-based image gallery that has just enough features to be really useful without a lot of work on my part to get it working. (Simple is always better - ;-].) Here's a screenshot of QDIG in action with some Bing photos:
(Click to enlarge photo.) |
The trouble is, QDIG creates some really heinous query string lines; see the URL line in the following screenshot for an example:
(Click to enlarge photo.) |
I don't know about you, but in today's SEO-friendly world, I hate long and convoluted query strings. Which brings me to one of my favorite subjects: URL Rewrite for IIS
If you've been around IIS for a while, you probably already know that there are a lot of great things that you can do with the IIS URL Rewrite module, and one of the things that URL Rewrite is great at is cleaning up complex query strings into something that's a little more intuitive.
It would take way to long to describe all of the steps to create the following rules with the URL Rewrite interface, so I'll just include the contents of my web.config file for my QDIG directory - which is a physical folder called "QDIG" that is under the root of my website:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<!-- Rewrite the inbound URLs into the correct query string. -->
<rule name="RewriteInboundQdigURLs" stopProcessing="true">
<match url="Qif/(.*)/Qiv/(.*)/Qis/(.*)/Qwd/(.*)" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="/QDIG/?Qif={R:1}&Qiv={R:2}&Qis={R:3}&Qwd={R:4}" appendQueryString="false" />
</rule>
</rules>
<outboundRules>
<!-- Rewrite the outbound URLs into user-friendly URLs. -->
<rule name="RewriteOutboundQdigURLs" preCondition="ResponseIsHTML" enabled="true">
<match filterByTags="A, Img, Link" pattern="^(.*)\?Qwd=([^=&]+)&(?:amp;)?Qif=([^=&]+)&(?:amp;)?Qiv=([^=&]+)&(?:amp;)?Qis=([^=&]+)(.*)" />
<action type="Rewrite" value="/QDIG/Qif/{R:3}/Qiv/{R:4}/Qis/{R:5}/Qwd/{R:2}" />
</rule>
<!-- Rewrite the outbound relative QDIG URLs for the correct path. -->
<rule name="RewriteOutboundRelativeQdigFileURLs" preCondition="ResponseIsHTML" enabled="true">
<match filterByTags="Img" pattern="^\.\/qdig-files/(.*)$" />
<action type="Rewrite" value="/QDIG/qdig-files/{R:1}" />
</rule>
<!-- Rewrite the outbound relative file URLs for the correct path. -->
<rule name="RewriteOutboundRelativeFileURLs" preCondition="ResponseIsHTML" enabled="true">
<match filterByTags="Img" pattern="^\.\/(.*)$" />
<action type="Rewrite" value="/QDIG/{R:1}" />
</rule>
<preConditions>
<!-- Define a precondition so the outbound rules only apply to HTML responses. -->
<preCondition name="ResponseIsHTML">
<add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
</preCondition>
</preConditions>
</outboundRules>
</rewrite>
</system.webServer>
</configuration>
Here's the breakdown of what all of the rules do:
- RewriteInboundQdigURLs - This rule will rewrite inbound user-friendly URLs into the appropriate query string values that QDIG expects. I should point out that I rearrange the parameters from the way that QDIG would normally define them; more specifically, I pass the value Qwd parameter last, and I do this so that the current directory "." does not get ignored by browsers and break the functionality.
- RewriteOutboundQdigURLs - This rule will rewrite outbound HTML so that all anchor, link, and image tags are in the new format. This is where I actually rearrange the parameters that I mentioned earlier.
- RewriteOutboundRelativeQdigFileURLs - There are several files that QDIG creates in the "/qdig-files/" folder of your application; when the application paths are rewritten, you need to make sure that the those paths won't just break. For example, once you have a path that is rewritten as https://localhost/QDIG/Qif/foo.jpg/Qiv/name/Qis/M/Qwd/, the relative paths will seem to be offset from that URL space as though it were a physical path; since it isn't, you'd get HTTP 404 errors throughout your application.
- RewriteOutboundRelativeFileURLs - This rule is related to the previous rule, although this works for the files in your actual gallery. Since the paths are relative, you need to make sure that they will work in the rewritten URL namespace.
- ResponseIsHTML - This pre-condition verifies if an outbound response is HTML; this is used by the three outbound rules to make sure that URL Rewrite doesn't try to rewrite responses where it's not warranted.
Once you have these rules in place, you get nice user-friendly URLs in QDIG:
(Click to enlarge photo.) |
I should also point out that these rules also support changing the style from thumbnails to file names to file numbers, etc.
(Click to enlarge photo.) |
All of that being said, there is one thing that these rules do not support - and that's nested folders under my QDIG application. I don't like to use folders under my QDIG folder - I like to use separate folders with the QDIG file in it, because this makes each gallery self-contained and easily transportable. That being said, after I had written the text for this blog, I tried to use a subfolder under my QDIG application and that didn't work. By looking at what was going on, I'm pretty sure that it would be pretty trivial to write some URL Rewrite rules that would accommodate using subfolders, but that's another project for another day. ;-]