Rewrite Trailing Slash Issue - apache

Here is my .htaccess file
Options +FollowSymlinks
RewriteEngine on
ErrorDocument 404 /404.php
RewriteRule ^(\d*)/(.*) /page.php?id=$1&slug=$2
It all works fine. But the moment I type site.com/342/my-page/ (with the trailing slash) I get a 404.
I need the trailing slash as optional. I.e it will redirect to the correct page with or without the slash.
I tried this, but it didn't work
RewriteRule ^(\d*)/(.*)/?$ /page.php?id=$1&slug=$2
Any ideas?

.* is greedy, so it will eat your trailing slash even if it does not have to. You have to force it to stay away like this:
RewriteRule ^(\d*)/(.*[^/])/?$ /page.php?id=$1&slug=$2
This is ensure that $2 is never ending with a slash

Related

htaccess rewrites causing side affects

I have the following in my .htaccess file.
RewriteEngine On
RewriteRule ^([^/]+)?$ /member/profile.php?user=$1 [L]
RewriteRule ^assets(/.*)?$ /member/assets$1 [L]
RewriteRule ^images(/.*)?$ /member/images$1 [L]
RewriteRule ^php(/.*)?$ /member/php$1 [L]
The desired effect is:
https://example.com/username -> https://example.com/member/profile.php?user=$1
This works, however, the issue is there are 2 undesired outcomes happening from this.
First: https://example.com and https://example.com/ return 404 errors but https://example.com/index.php works just fine.
Second: https://example.com/username/ ends up forwarding to https://example/member/php/?user=username and returning a 404 error.
I have also attempted
DirectoryIndex index.htm index.html index.php
But this seems to have no effect on the issue
My actual desired end result would look more like:
https://example.com -> https://example.com/index.php
https://example.com/ -> https://example.com/index.php
https://example.com/username -> https://example.com/member/profile.php?user=$1
https://example.com/username/ -> https://example.com/member/profile.php?user=$1
RewriteRule ^([^/]+)?$ /member/profile.php?user=$1 [L]
First: https://example.com and https://example.com/ return 404 errors but https://domain.name/index.php works just fine.
The first rule will catch the request (since it allows an empty URL-path) and will rewrite the request to /member/profile.php?user=. So, presumably it is your script that is triggering the 404?
In fact, it looks like you are missing a slash before ? to match an optional trailing slash (ie. /username or /username/), rather than making the entire pattern optional! ie. ^([^/]+)/?$
You would also need the NS (nosubreq) flag to prevent the subrequest by mod_dir for the DirectoryIndex (ie. index.php) also being caught by this rule. However, this rule is arguably matching too much, as it will also catch direct requests for index.php (and any other files you might have in the root). So, maybe you need to be more restrictive in what characters are allowed in usernames? For example, at a minimum, exclude dots (as well as slashes) with ^([^/.]+)/?$? Or allow only letters and numbers (and underscores), eg. ^(\w+)/?$. (\w is a shorthand character class that represents [0-9a-zA-Z_].)
Note that the first rule will also match assets, images and php - so these are valid usernames. Is that intentional? You could reverse the rules so this does not happen, but you would need to ensure that there are no usernames that match these strings.
NB: https://example.com and https://example.com/ are exactly the same request. (The browser effectively appends the slash after the hostname to make a valid HTTP request. See the following question on the Webmasters stack: Is trailing slash automagically added on click of home page URL in browser?)
Second: https://example.com/username/ ends up forwarding to https://example.com/member/php/?user=username and returning a 404 error.
I can't see how that would happen with the directives as posted. None of your rules would match /username/ (with a trailing slash), unless the username is "assets", "images" or "php" - but that still wouldn't result in the stated rewrite? However, /username/ would result in a 404 because nothing actually happens to rewrite the URL!
Your rules should perhaps be written like this instead:
RewriteEngine On
RewriteRule ^(\w+)/?$ member/profile.php?user=$1 [L]
RewriteRule ^assets(/.*) member/assets$1 [L]
RewriteRule ^images(/.*) member/images$1 [L]
RewriteRule ^php(/.*) member/php$1 [L]
The capturing subpattern in rules 2, 3 and 4 is not optional, so I've removed the trailing ?$.
I've also removed the slash prefix on the substitution string, to make it a relative file-path.
Which could also be further "simplified" to:
RewriteEngine On
RewriteBase /member
RewriteRule ^(\w+)/?$ profile.php?user=$1 [L]
RewriteRule ^((assets|images|php)/.*) $1 [L]

.htaccess rewrite rule for URL with round bracket

The company I work for just recently sent out a mass email and got the URL for the footer wrong. The correct URL is /email/footer.png, but the email has the URL /email/footer.png) (note the trailing bracket).
I have tried the following .htaccess RewriteRule with no luck. RewriteEngine is on, mod_rewrite.c is loaded, and rewrites are working for a number of other RewriteRules:
RewriteRule ^/email/footer\.png\)$ /email/footer.png
Does anyone know the fix for this?
You need to remove the leading slash from your uri pattern
RewriteEngine on
RewriteRule ^email/footer\.png\)$ /email/footer.png [L,R]

RewriteRule, url wrongly displayed

I am new to mod_rewrite and I have this problem:
I have a working redirect with mod_rewrite, my .htaccess:
RewriteEngine on
RewriteRule ^microsite/([^/\.]+)/$ micrositecontroller.php?name=$1 [L]
micrositecontroller.php only echoes a text
On the browser when I enter my URL:
localhost/project/microsite/test/
I am redirected to where wanted but when I enter:
localhost/project/microsite/test
It still redirects to where wanted but the URL becomes like this:
localhost/project/microsite/test/?name=test
Now what I want is that trailing "/?name=test" not to show up.
I tried different combinations of the regex but to no avail and I have no idea if it is normal of not. Any idea?
You have a slash in your regex, so your regex handles slash... just remove it:
RewriteEngine on
RewriteRule ^microsite/([^/\.]+)$ micrositecontroller.php?name=$1 [L]
What you want is:
RewriteEngine on
RewriteRule ^microsite/([^/\.]+)/?$ micrositecontroller.php?name=$1 [L]
# Note the "?"-------------------^
To accommodate both ending with a slash and no slash. The problem with leaving the slash on (or off) is apache forces a browser redirect, thus making the ?name=test show up in the browser's location bar.
This is because mod_dir and the DirectorySlash on directive is interferring. The DirectorySlash directive tells apache to redirect the browser when it accesses what looks to be a directory (in your case localhost/project/microsite/test to the smae URI except with a trailing slash.

Ignore trailing slash with Apache Rewrite

I'm using mod_rewrite to redirect like so:
RewriteRule (work)/?$ $1.php [L]
This sends any URL ending in /work or /work/ to work.php
The problem is, when a trailing slash is included, it treats it as a directory, and not the file that it really is. This, of course, breaks all of my relative paths in the file.
I don't mind having a slash in the URL, but is there any way to use Apache to ignore the trailing slash, and treat the URL as a file, just as it would without the slash?
Since you don't want the URL to look like www.domain.com/work/ here's what you can do:
RewriteEngine On
RewriteRule ^work/$ http://www.domain.com/work%{REQUEST_URI} [R=301,L,NC]
RewriteRule (work)$ $1.php [L,QSA,NC]
This will redirect /work/ to /work and /work/?page=main to /work?page=main

.htaccess same url with or without /

I am doing a painful rewrite of many urls on a website I am currently working on, but I have noticed a small problem:
RewriteRule ^domains/transfer$ ./cart.php?gid=11 [L,NC]
This line with navigate if I go to:
http://my-site/domains/transfer
But it won't work with a trailing /:
http://my-site/domains/transfer/
Is there a way I can change the RewriteCode to take either argument and go to the same page. It seems wasteful to have the same line twice to include a '/'
Any help would be appreciated.
Cheers
Change the line to this:
RewriteRule ^domains/transfer/?$ ./cart.php?gid=11 [L,NC]
The magic is here: /? and that allows for the preceding character, in this case the slash (/), to be optional.
If you want something to come after the transfer, then remove the dollar sign ($) which marks the end of the allowable matching.
I would recommend you to allow just one URL form, the one with or without the trailing slash, and redirect if malformed:
# remove trailing slash
RewriteRule (.*)/$ /$1 [L,R=301]
# add trailing slash
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .*[^/]$ /$0/ [L,R=301]