htaccess - How to remove everything after preceeding trailing slash in URI - .htaccess

I have 2 url patterns :
http://www.mondomaine.com/m/99/some-title-etc/
http://www.mondomaine.com/w/287/some-title-etc/
I want to hide/delete everything after the slash following the ID number, how would I do that in .htaccess file so it looks like this:
http://www.mondomaine.com/m/99/
http://www.mondomaine.com/w/287/
Of course, numbers are ID numbers. There are many of them and they are all different, I just show examples of the 2 patterns.
Here is what I have in my .htaccess file that is relevant to the /m/ part (similar for the /w/ part):
RewriteCond %{REQUEST_URI} m.*
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^m(.*)$ articles.php?$1 [T=application/x-httpd-php,L]
(I saw plenty of solutions here but none for my exact situation).

Updated again:
This does as you require for any folder structure.
RewriteEngine On
#RewriteCond %{REQUEST_FILENAME} !-d -Due to comments no longer needed.
#RewriteCond %{REQUEST_FILENAME} !-f -Due to comments no longer needed.
RewriteRule ^(.*)/(.*/+)$ /$1 [NC,L,QSA]
#RewriteCond %{REQUEST_FILENAME} !-d -Due to comments no longer needed.
#RewriteCond %{REQUEST_FILENAME} !-f -Due to comments no longer needed.
RewriteRule ^(.*)/(.*)$ /$1 [NC,L,QSA]
Line one:
Turn on Rwrite.
Line two:
Check that file requested is not a directory.
Line four: Remove all content after the final slash if there is an ending slash in the URI, this is removed and then page is directed to the new link.
Then the checks break because only one rewrite Rule can be applied at a time, so the first rule is applied and the URI is reloaded. then the second will be reached:
Line five: Is it a directory? No.
Line six: Is it a file? No.
Line seven: Remove everything after the final /. finish and visit the new location.
QSA = Query string append. ?this=aquerystring
L = Last, last rule applied before visiting the newly generated destination path.
NC = Not case sensitive.

Related

Difficulty with .htaccess determining which file to use based on final page backslash '/'

I have two types of pages in a section of my website.
One is for a categories, for example:
example.com/section/fruit/
example.com/section/vegetables/
The other for page details, for example:
example.com/section/fruit/apple
example.com/section/fruit/orange
example.com/section/fruit/grape
I am using .htaccess to grab the urlslug and talk to the database to display the right information and use the right template file.
RewriteCond %{REQUEST_URI} /section/(.*)/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule section/(.*)/ /template/category.php?urlslug=$1 [L]
RewriteCond %{REQUEST_URI} /section/(.*)/(.*)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule section/(.*)/(.*) /template/detail.php?category=$1&urlslug=$2 [L]
Unfortunately, because I have two url display methods the above .htaccess does not work. For categories they end in a ‘/‘ and the page detail are open (no slash) and .htaccess file cannot work out which one to grab.
I guess the question here is two fold.
From a best practice point of view. Is it better to have one consistent convention for URLs (all of them having an end slash or no end slash)? My current reasoning is that pages without a slash are the end page and the ones with a slash are categories but am not sure my logic is awesome on this one.
Assuming what I am doing is okay from a URL structure point of view. What would be the best approach to get the .htaccess to behave?
You may use these rules:
# skip below rules for files or directories
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^section/([\w-]+)/?$ template/category.php?urlslug=$1 [L,NC,QSA]
RewriteRule ^section/([\w-]+)/([\w-]+)/?$ template/detail.php?category=$1&urlslug=$2 [L,QSA,NC]
Note that .* matches everything. Using anchors in regex patterns allows you to match only one path component after /section/.

Rewrite URL with .htaccess for multiple parameters

This question might be a duplicate. But I did not find any solution worked for me.
I want to rewrite URL, where I have one and two level parameters. first parameter is p and second is sp
www.domain.com/home should point to www.domain.com/index.php?p=home
and
www.domain.com/projects/99 should point to www.domain.com/index.php?p=projects&sp=99
How do I do in .htaccess?
Currently My htaccess is as followes,
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?p=$1
RewriteRule ^([^/]*)/([^/]*)\$ index.php?p=$1&sp=$2 [L]
The problem with this htaccess is that it correctly points one level url. ie., www.domain.com/home. But not the two level url. ie. www.domain.com/projects/99
You have to treat the rules separately. All Conditions preceding rules only apply to a single, immediately following rule. You tried to 'chain' two rules. The second rule never could have matched, since the first one was a catch-all that changed the syntax. Apart from that you have to make sure that the first rule does not catch unwanted requests. Also think about whether you want to use the * or the + operator in the patterns. I suggest you use the + operator, so that you have a clear error message when empty values are requested for a 'page' or a 'subpage'.
So this might come closer to what you are looking for:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)$ index.php?p=$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+)$ index.php?p=$1&sp=$2 [L]

Add a trailing slash mod_rewrite

just wondering how I add a trailing slash at the end of my URLs using Mod_Rewrite?
This is my .htaccess file currently:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]*)$ index.php?pageName=$1
My URL show like so:
wwww.******.com/pageName
I want it to show like so:
wwww.******.com/pageName/
The URL is holding a GET request internally, but I want it to look like a genuine directory.
You can easily add a trailing slash to the URL that a client sees, but you'll have to take into account that trailing slash in requests that you get after you've redirected the browser.
So the redirect could look something like this:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*[^/])$ /$1/ [L,R=301]
And you'll want it above the:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]*)$ index.php?pageName=$1
ruleset, because the redirect needs to happen before the routing to index.php. Note that when the browser gets redirected to a URL that ends with a /, your index.php rule will have the pageName param with a trailing slash in it.
I know this is old, but it's still useful for others that find it.
Jon Lin's answer is correct, I would add this as a comment but I don't have enough reputation.
The OPs comment about removing the trailing slash, since you know it will always have a slash at the end, you could $pageName = substr($pageName, 0, -1);. That's what I'm doing at least.
Hope this is useful.

htaccess does not work rewrite rule

I've been struggling with my .htaccess file for weeks now, I changed it many times but it just won't work.
I have this in my .htaccess file:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^/([^./]+)\.html$ category.php?id=$1
RewriteRule ^/([^./]+)\.html$ tag.php?id=$1
RewriteRule ^/([^./]+)\.html$ play.php?id=$1
but it does not work.
Are you sure that mod_rewrite is turned on in Apache? Do you have access to httpd.conf? It would be better to do redirects there instead of with a .htaccess file.
Your conditions are only being applied to the first rule. Each set of RewriteCond's only get applied to the immediately following RewriteRule. So the conditions only get applied to RewriteRule ^/([^./]+)\.html$ category.php?id=$1 and the last 2 rules have no conditions at all.
Your conditions is to rewrite something that exists to something else, which will cause a rewrite loop. You probably wanted:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
Your 2nd and 3rd rules will never be applied because if someone requests /some-page.html the first rule's regex will match it and rewrite the URI to /category.php?id=some-page, then the next to rules will never match because the first rule already rewrote the URI to category.php.
Your regular expressions match a leading slash, URI's being applied in rewrite rules that are inside an htaccess file has the leading slash stripped out, so you want this instead:
RewriteRule ^([^./]+)\.html$ category.php?id=$1
1, 2 and 4 is easy. 3, not so much. You're going to have to figure out a unique way to represent an html page as a category, tag, or play. You can't have all 3 look identical, there's no way to tell which one you want. Take:
/something.html
Is that supposed to be a category? A tag? or a Play? Who knows, your rewrite rules surely don't. But if you preface each with a keyword, then you can differentiate:
/category/something.html
/tag/something.html
/play/something.html
And your rules would look like:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^category/([^./]+)\.html$ category.php?id=$1
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^tag/([^./]+)\.html$ tag.php?id=$1
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^play/([^./]+)\.html$ play.php?id=$1

htaccess directory to file redirect problem

I’m trying to use the following .htaccess file
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^images/
RewriteRule (.*) view.php?picid=$1 [L]
RewriteRule ^/user/(.*)$ /users.php?user=$1
I want two things to happen: Whenever someone requests /1234, it redirects to /view.php?picid=1234, and also when someone visits /users/bob, it redirects to /users.php?user=bob.
My code however, doesn’t seem to be working correctly.
There are several ways to do that. Here’s one that should work:
RewriteRule ^user/(.+)$ users.php?user=$1 [L]
RewriteRule ^([0-9]+)$ view.php?picid=$1 [L]
The first rule will catch any request that’s URI path begins with /user/ followed by one or more arbitrary characters. And the second will catch any request that’s URI path begins with / followed by one or more digits.
The initial problem with your rules is that the RewriteRule with (.*) will match everything.
If you do not want it to match a URL with a slash in it (such as users/bob), try ^([^/]*)$
Secondly, after a URL is rewritten, the new URL goes through your rules again. If you want to avoid matching something that has already been rewritten once, you should add a condition like
RewriteCond %{REQUEST_URI} !\.php

Resources