Rewrite rule for invalid query

For a rewrite that seems to work, I want to be sure it’s really correct, lest there be some possible error I’m unaware of.

I’m using this:


RewriteRule ^(\\d+)$ index.php?a=$1
RewriteRule ^([\\D+]|[\\D|\\d]+)$ index.php [L]

to do this


slideshow/12      =>     slideshow/index.php$a=12

The first rule handles numbers (with the index.php handling out-of-range numbers), and for thoroughness I want any invalid queries such as


slideshow/hgyt
slideshow/23ab
slideshow/23&

to go index.php with no query string.

I’m hoping the second rule’s condition says: “any non-numeric or any mix of numeric and non-numeric”. It seems to work.

Is it fully correct?

Thank you.

First let’s analyze what you have so far.

  1. The plus sign needs to go outside the character class.

Before
[\D+]

After
[\D]+

In fact, in this specific situation, you don’t need a character class at all.

After
\D+

  1. When inside a character class, the “|” character does not mean “or”. It’s simply treated as the literal “|” character.

Before
[\D|\d]+

After
[\D\d]+

  1. Matching all non-digit characters, as well as all digit characters, effectively means you’re matching on any character.

Before
[\D\d]+

After
.+

  1. That the second part of your ORed pattern will match anything makes the first part redundant.

Before
FONT=Courier New[/FONT]

After
FONT=Courier New[/FONT]

And that’s what your pattern boils down to.

What you could have done is simply this:

RewriteRule \D index.php

Note the lack of any “^” start or “$” end anchors. This way, it doesn’t matter where in the string the non-digit character matches. You’re simply detecting whether a non-digit character exists.

Note also that the path “index.php” contains non-digit characters, so you’ll also be rewriting “index.php” to “index.php”. It’s not the worst thing in the world, but if you want to avoid it, you can create a rewrite condition.

[FONT=Courier New]# Use the next rewrite rule only if the URL isn’t already pointing to a real file
RewriteCond ${REQUEST_FILENAME} !-f

RewriteRule \D index.php[/FONT]

With all that out of the way, let’s examine some of your attempts at validation.

The first rule handles numbers (with the index.php handling out-of-range numbers), and for thoroughness I want any invalid queries to go index.php with no query string.

The problem with using rewrite rules to identify and correct for invalid URLs is that there’s nothing stopping me from bypassing your pretty URLs and typing the real URL in my address bar instead.

slideshow/index.php?a=hgyt

Which means your PHP must be able to handle invalid queries. And if your PHP is already capable of handling invalid queries, then there’s no point in using rewrite rules to apply an extra and ineffective layer of validation. I would get rid of both your rewrite rules and simply do this:

RewriteCond ${REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?a=$1 [QSA]

Thank you. This works perfectly. I’ve added an is_numeric() filter to the index file.

The detailed explanation is much appreciated – good learning for a beginner wanting thorough understanding.

Puzzling result now:

This works perfectly in my local server (Mac Apache) but not in my remote server (Linux Litespeed).

I had a typo.

RewriteCond ${REQUEST_FILENAME} !-f

should be

RewriteCond %{REQUEST_FILENAME} !-f

… should be

RewriteCond %{REQUEST_FILENAME} !-f

Thank you. Now it works perfectly.

(I wonder why ${REQUEST_FILENAME} does work in my local Apache…?)

Your help is much appreciated.