Marc Eickhoff
Marc Eickhoff

Reputation: 102

mod_rewrite and hyperlinks with spaces

So I'm no .htaccess expert, by no means, but I have managed to put this code together for a webiste I'm making:

Options -Indexes +Includes
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_URI}::$1 ^(.*?/)(.*)::\2$
RewriteRule ^(.*)$ - [E=BASE:%1]
RewriteRule ^\.htaccess$ - [F]
RewriteRule ^$ /%{ENV:BASE}/index.php?id=home
RewriteCond %{REQUEST_URI} !\.php$ [NC]
RewriteCond %{REQUEST_FILENAME} !-s
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ $1 [R=301,L]
RewriteRule ^([a-zA-Z0-9]*)$ /%{ENV:BASE}/index.php?id=$1 [QSA,L]
</IfModule>

It basically changes www.example.com/some/dir/index.php?id=home to www.example.com/some/dir/home while the first few rules are creating some kind of relative path value so I don't have to change the RewriteBase everytime I change the base folder (this is important for this project!).

It works perfectly fine, but now I have encountered a problem where there have to be spaces in the URL like www.example.com/some dir/sub folder/home and this messes everything up.

If you click a link on the page (e.g. "href="home"") it redirects to www.example.com/home instead of www.example.com/some dir/sub folder/home with a 404 error, obviously (even though it works if there are no spaces!). I found out if right click > "copy link to clipboard" it becomes the encoded version www.example.com/some%20dir/sub%20folder/home even if it shows the decoded version in the address bar. BUT if you manually type the decoded version www.example.com/some dir/sub folder/home it still works fine.

There seems to be a problem with spaces and encoding. How do I get my hyperlinks working properly?

-- EDIT -- Thanks to the tutorial posted by elcodedocle, I simply added backslash space: ^([a-zA-Z0-9/ ]*)$ to the regex in the last rule, even if it's not the best method. Then I noticed the [L] flag in the second last rule. I removed it because this shouldn't be the last rule (don't know why it was there in the first place...) and now it works! Well, kind of...

Now, If there is a trailing slash at the end of the URL it sill doesn't work anymore. Probabply because of the removal of the [L] flag in the rule but I don't know how to fix this...

Upvotes: 2

Views: 316

Answers (2)

anubhava
anubhava

Reputation: 784878

Have your .htaccess like this:

Options -Indexes +Includes -MultiViews

<IfModule mod_rewrite.c>
RewriteEngine on

RewriteCond %{REQUEST_URI}::$1 ^(.*?/)(.*)::\2$
RewriteRule ^(.*)$ - [E=BASE:%1]

RewriteCond %{REQUEST_URI} !\.php$ [NC]
RewriteCond %{REQUEST_FILENAME} !-s
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ %{ENV:BASE}$1 [R=302,L,NE]

RewriteRule ^\.htaccess$ - [F]

RewriteRule ^$ /%{ENV:BASE}/index.php?id=home [L,QSA]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+?)/?$ %{ENV:BASE}index.php?id=$1 [QSA,L]
</IfModule>

This is working fine under all the test cases you have described in your question like handling spaces, trailing slashes etc.

Upvotes: 2

NotGaeL
NotGaeL

Reputation: 8484

Try changing:

RewriteRule ^([a-zA-Z0-9]*)$ /%{ENV:BASE}/index.php?id=$1 [QSA,L]

to

RewriteRule ^([a-zA-Z0-9%]*)$ /%{ENV:BASE}/index.php?id=$1 [QSA,L]

(It's a wild guess but it's the only one of your rules that has problems with %)

[EDIT] Unencoded spaces are not allowed in URIs. The ban on spaces is enforced by all browsers as they will convert every space to %20 before sending the request via the http protocol. A workaround to handle them in mod_rewrite is described on this tutorial:

Since URLs can't have spaces (except as %20), use underlines or hyphens to replace them. If you ABSOLUTELY have to use spaces (%20) in your URIs, you can include them in your regex within a range definition as {space}, i.e., ([a-zA-Z\ ]+). However, this is NOT advised.

[EDIT2] If that doesn't work, you may have to translate %20 into spaces, then apply the other rules. Here is a hack based on this answer you may try:

sedspace.sh:

#!/bin/sh
sed -u 's/%20/ /g'

.htaccess:

...
RewriteMap sed-space prg:sedspace.sh
RewriteRule ^(.*)$ ${sed-space:$1}
...

(Make sure that sedspace.sh is executable)

Upvotes: 1

Related Questions