Skip to content
Advertisement

Unwanted backslash on parameter while using RewriteRule

URL Examples:

1) mydomain.com/coding/mysql/
2) mydomain.com/coding/mysql/?contactId=333&UTM=aff
3) mydomain.com/coding/?contactId=333

This is my htaccess file

RewriteEngine On
RewriteRule ^(.+)/(.+)/?$ index.php?book=$1&chapter=$2 [NC,L,QSA]
RewriteRule ^(.+)/?$ index.php?book=$1 [NC,L,QSA]

So I print_r($_REQUEST) on the index.php file to see what I was getting:

1) Array ( [book] => coding [chapter] => mysql/ )
2) Array ( [book] => coding [chapter] => mysql/ [contactId] => 333 [UTM] => aff )
3) Array ( [book] => coding/ [contactId] => 333 [UTM] => aff )

My problem is that I don’t want the / showing in the last available parameter It would not add the / if I call the examples above like this:

1) mydomain.com/coding/mysql
2) mydomain.com/coding/mysql?contactId=333&UTM=aff
3) mydomain.com/coding?contactId=333

What do I need to change on my rules to have mydomain.com/coding/mysql?contactId=333&UTM=aff resulting in Array ( [book] => coding [chapter] => mysql [contactId] => 333 [UTM] => aff )

Thanks! Much appreciated. I hope that makes sense.

Advertisement

Answer

RewriteRule ^(.+)/(.+)/?$ index.php?book=$1&chapter=$2 [NC,L,QSA]
RewriteRule ^(.+)/?$ index.php?book=$1 [NC,L,QSA]

Regex is greedy by default, so in the case of (.+)/?, the capturing group will consume the optional / that follows.

You could make the quantifier non-greedy (ie. lazy) like this: (.+?)/? or match “anything except a slash” (ie. [^/]+) instead of just “anything” (ie. .+).

For example:

RewriteRule ^index.php - [L]
RewriteRule ^([^/]+)/([^/]+)/?$ index.php?book=$1&chapter=$2 [L,QSA]
RewriteRule ^([^/]+)/?$ index.php?book=$1 [L,QSA]

UPDATE: The first rule is simply to prevent a rewrite-loop, since the pattern ^([^/]+)/?$ would also match index.php (the rewritten URL-path).

The NC flags are not required here since you are matching both lowercase and uppercase everything anyway.


However, you should be consistent with your trailing slashes and either include a trailing slash or omit it – you shouldn’t really allow both and have both serve the same content. This is potentially a “duplicate content” issue (two URLs serving the same content).

If you want to allow both then 301 redirect from one to the other.


UPDATE:

yeah so I have a file locate at mydomain.com/library.php when I try to access it I get this instead of the actual file Array ( [book] => library.php )

(Aside: If you are only matching/forcing trailing slashes – as mentioned in comments then this wouldn’t necessarily be an issue.)

This is because the regex above is rather generic. It matches /<any-path-segment>. If your URLs (that you want to rewrite) don’t contain a dot then you could simply exclude a dot in the regex to avoid matching “files” that have a file extension (like .php or .js etc.).

For example, modify the above regex as follows to exclude dots:

RewriteRule ^([^/.]+)/([^/.]+)/?$ index.php?book=$1&chapter=$2 [L,QSA]
RewriteRule ^([^/.]+)/?$ index.php?book=$1 [L,QSA]

This will match foo, but not foo.txt (because it contains a dot).

This also avoids the need to have the first rule that matches index.php, since this is naturally excluded by the more specific regex.

Generally, you should be as specific as possible with the regex and only match what is required, to avoid accidentally matching too much.

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement