databaseapacheurlmod-rewritezope

Use Apache to Rewrite URLs with Database Parameters as Nice URLs


For years our database driven websites have had URLs that look like: https://www.example.com/product?id=30

But nowadays, and especially for SEO purposes, we want our URLs to be "nice" and look like: https://www.example.com/30/myproduct

We use Zope 2.13.x running on Debian and using Apache 2.4 as the front-end webserver. I know that not too many people use Zope, but utilizing Apache's mod_rewrite we should be able to proxy the rewrite and have nice URLs that still pass the database arguments necessary in order to properly serve the pages to the end users.

There used to be a Zope Cookbook where I wrote a bunch of really detailed tutorials on Zope functionality but that no longer seems to exist and I wanted to share this with the SE community.

The awesome thing is that this is not specific to Zope, but will/should work with any rewrite of a parameter based URL into a nice URL and it's super easy once it's all working.

For complete transparency, I am going to answer my own question so that it's documented for everyone.


Solution

  • Using the rewrite engine in Apache, decide how you want your URLs to look to the end user in their web browser.

    For example, if you are calling to a database and have a url that looks like

    https://www.example.com/products?id=30&product_name=myproduct

    but you want that URL to look like

    https://www.example.com/products/30/myproduct

    you would use a rewrite rule as follows:

    RewriteRule ^/products/(.*)/(.*) /products?id=$1&product_name=$2 [L,P,NE,QSA]
    

    To explain that further:

    ^/products/(.*)/(.*) is saying that anytime domain.com/products is accessed, look for two variables in the next directory names, i.e. /(.*)/(.*)

    If you only wanted one variable you would do ^/products/(.*)

    Likewise if you wanted three variables you would do ^/products/(.*)/(.*)/(.*)

    From there we need to tell Apache how to interpret that URL in order to rewrite and still allow Zope (or whatever db you may be using) to pass the correct URL parameters. That part is:

    /products?id=$1&product_name=$2
    

    Apache will now take the first (.*) and treat that as $1. It will take the second (.*) and treat that as $2 and so on.

    The part in the brackets is extremely important

    L = This makes Apache stop processing the rewrite ruleset if the rule matches. This is important because you don't want Apache to get confused and start trying other rewrites.

    P = Proxy the request. This makes sure that the browser does not display a different URL than https://www.example.com/products/30/myproduct (i.e. we do not want the end user seeing the rewritten URL as https://www.example.com/products?id=30&product_name=myproduct

    NE = No Escaping any URL characters. You need this to ensure that the URL rewrite does not try and escape the special characters like $ = & as these are important to URL parameters

    QSA = This allows multiple variables (or URL parameters) to exist

    Please Note: It is very important to consider how you want your URLs to look (the nice URLs) because that is what you want to submit to the search engines. If you change your URL structure, those nice URLs will no longer work and your search engine rankings may decrease.