URL Routing in Perch Runway

One of great strengths of Perch has always been that you can drop editable regions into an existing site. This is down to the way Perch helps you manage content across a set of pages. If a site grows beyond a certain scale, maintaining that set of pages can become a bit of an overhead. What is an advantage for small sites becomes a disadvantage for larger ones.

The aim of Perch Runway is to skew the features of Perch to fit more comfortably with those larger sites, and in the process make building and managing larger sites much more efficient and pleasurable.

Doing away with pages

The first step is to get rid of those troublesome page files. In Perch Runway, every URL is routed through to a Master Page. The Master Page then pulls in layouts and content regions to piece the page together.

To give an example, you might have a Master Page set up as a blog post detail page. In order to make sure any requests for blog post pages get routed through to the right Master Page, Runway needs to do some pattern matching on the URL.

Traditionally with Perch, you might have stuck with ugly URLs, else you’d have written some web server rewrite rules to do this for you.

Avoiding mod_rewrite and .htaccess

If you’ve spent any time writing (and therefore, inevitably, debugging) rewrite rules, you’ll know how much of a pain it can be. Even those experienced with both URL rewriting and regular expressions, it can see be a bit of a headache at times. We wanted to avoid that headache as much as possible, while still providing a flexible and powerful way to match URLs.

Writing legacy URLs aside, most carefully designed URL schemes end up matching for the same few things over and over again. A year, a number, a date or perhaps a lowercase letters, numbers and dashes slug. Our blog post page might have a URL like the below:

/blog/2014/url-routing-in-runway

To break that down into its parts, it’s the blog folder, then a year and then a slug. In Runway, the pattern to match this URL would be:

blog/[year]/[slug]

The [bracketed] items are placeholders, we call them tokens. The [year] token matches a four-digit year, and then [slug] token matches a lowercase letters, numbers and dashes sequence. There are tokens for numbers [i], letters [a], dates [isodate] and so on, for the common parts of a URL you might want to find. We think it makes writing patterns pretty easy.

For Runway to be able to handle all requests, there’s obviously a need to do some web server URL rewriting. With Runway, we give you one simple set of rules to use to route all page traffic to Perch and then handle the rest within the CMS itself.

Naming segments

Matching the URL is one thing, but the next logical step is that you want to use parts of that URL to do things in your page. In our blog post example, we’d want the slug in order to be able to look up the correct post.

To do that, you just add the name to the token. Let’s say I want to use the slug as postslug within my page. I’d modify the pattern to be:

blog/[year]/[slug:postslug]

The [slug:postslug] token means simply “a slug named postslug”. You’d use it in your page with:

perch_get(‘postslug’)

In your templates, we prefix the name with url_ to avoid naming conflicts with your own template IDs:

<perch:content id="url_postslug" />

Advanced features

You can match from multiple options. The below would match /product/view/1234 and /product/order/1234 with the view or order being passed through as action and the product ID as product_id:

users/[view|order:action]/[i:[product_id]

Another example, to offer a report in XML, CSV or JSON format:

report.[xml|csv|json:format]

Custom tokens

Of course, we don’t pretend to know exactly how your URLs will be formed and what sort of tokens you wish to match. For this reason, you can set up custom tokens in your site configuration.

At this point, there’s no getting away from the fact that you need to know regular expressions, unfortunately. The idea with custom tokens is that you can write and test your regular expression just once, and then use it by name from that point on. What’s more, as you’re matching just a small part of a URL with a token, they’re simpler to write and can also be shared.

As an example, say you needed a token for a product SKU in the URL. The SKUs the client uses are 3 numbers followed by 3 letters, like abc123. Your custom token definition would look like this:

‘sku’ => ‘[a-z]{3}[0-9]{3}’

Once that’s been defined, you can use it in your routing patterns without needing to think about it again:

product/[sku]/reviews

We hope this will take a lot of a headache out of URL rewriting in Perch Runway, while still providing lots of flexibility and convenience.