rewriterule how to handle no ending slash - .htaccess

I try to redirect anything coming into a directory to another. the rewriterule command I use is :
RewriteRule ^VirtualDirectory(.*)$ GENS/RealDirectory$1 [L,NC]
The thing is that I'd like that a query with no end slash to VirtualDirectory to be rewritten as if the query was for VirtualDirectory/
The behaviour I get is :
query to VirtualDirectory/ works great without the user noticing
query to VirtualDirectory workd great but the url shown in the brwoser is : GENS/RealDirectory/
I've tried many things but I can't get the behaviour I want.
If I add a rule
RewriteRule ^VirtualDirectory$ GENS/RealDirectory/ [L,NC]
to handle that specific case, it works great except that all resources of the page are rewrited to the folder before VirtualDirectory

What's happening is the internal rewrite is happening without a trailing slash, then mod_dir takes over and does a browser redirect to the same URL but with a trailing slash. You can turn off mod_dir by using DirectorySlash Off in your .htaccess file. If you want the trailing slash always, try changing the rule to this:
RewriteRule ^VirtualDirectory/?(.*)$ GENS/RealDirectory/$1 [L,NC]

Related

.htaccess folder as parameter to root index.php

What I need is any subfolder to be passed as a parameter to the root index.php
This is the code and it actually works.
RewriteEngine On
RewriteBase /
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} -d
RewriteRule ^(.+?)(/[^/]*|)$ index.php?dir=$1/ [L,QSA]
There is a problem:
When the url is like this (no end slash after 'projects'):
http://example.com/projects
the rewrite rule changes the link in the address bar and it looks like this:
http://example.com/projects/?dir=projects/
Is there a chance the url in the address bar always stays the same(no matter if there is an end slash or not) so the dir parameter is not visible to the user?
I tried with multiple rules - the first one to add an end slash, and then the second rule to pass the directory as parameter, but with no luck so far.
EDIT: so far thanks to w3d I managed to get it working. In the .htaccess just add:
DirectorySlash Off
tl;dr Make the trailing slash mandatory in the RewriteRule pattern (and remove the DirectorySlash Off directive, ie. keep it On).
RewriteRule ^(.+)/$ index.php?dir=$1/ [L,QSA]
As suggested in comments, this "strange" redirect is the result of mod_dir's DirectorySlash On directive, which is On by default. This can be quickly resolved by including DirectorySlash Off at the top of your .htaccess file (or making the trailing slash mandatory - see above and below).
The DirectorySlash On directive instructs Apache to automatically append a slash to URLs that end in a file system directory. In this sense it is "fixing" the URL. mod_dir achieves this with a 301 external redirect.
So, what is actually happening in the above, when DirectorySlash is enabled, is:
Initial request:
/projects (no trailing slash)
Internal rewrite in .htaccess:
/index.php?dir=projects/ (note that the request URL is still /projects)
mod_dir now kicks in and "fixes" the initial request (/projects --> /projects/) by appending a slash to the end of the URL-path. However, the query string from the rewritten URL (above) is passed through:
/projects/?dir=projects/ (this is a 301 external redirect, ie. a new request!)
Internal rewrite in .htaccess (again - new request):
/index.php?dir=projects/&dir=projects/ (note that the request is still /projects/?dir=projects/)
The doubling of the dir=projects/ query param is a result of the QSA flag on the RewriteRule (which I assume is required for other requests?). Your PHP script simply sees a single dir GET param (the later overwrites the former), unless you included dir[]=$1/ in your RewriteRule and you will end up with a 2-element array!
Your RewriteRule pattern also looks unnecessarily complex. You could simply make the trailing slash optional. ie:
RewriteRule ^(.+?)/?$ index.php?dir=$1/ [L,QSA]
Alternatively, having said all the above, you should probably leave DirectorySlash On (default) and simply make the trailing slash mandatory! For example:
RewriteRule ^(.+)/$ index.php?dir=$1/ [L,QSA]
mod_dir will now kick in before your internal rewrite (since it won't match without a trailing slash). This is also better for canonicalising your URLs and there are also potential security risks with turning it off.
Reference:
http://httpd.apache.org/docs/2.2/mod/mod_dir.html#directoryslash

Why doesn't this URL rewrite work?

This is a page on my domain: www.mydomain.com/en/stats.php
I want it to look like this: www.mydomain.com/en/statistics/players
This is pretty simple to accomplish, but for some reason the htaccess code below doesn't work.
Options +FollowSymLinks
RewriteEngine On
RewriteRule ^/statistics/players stats.php [R=301,L,QSA]
I get a 404 error when I try to open the SEO-friendly version. The page opens fine when I use the regular URL. What am I doing wrong?
The URL might not have a leading slash. Try without or optional slash. Additionally, you must check for the leading en, when you anchor your pattern at the beginning
RewriteRule ^/?en/statistics/players /en/stats.php
What worked in the end is the following:
RewriteRule en/statistics/players en/stats.php [NC,L]
I think it needs to be:
RewriteEngine On
RewriteRule ^en/statistics/players en/stats.php [QSA]
The R=301 means it will perform a redirect instead of a rewrite and try to redirect to /stats.php which doesnt exists I guess.
The L flag means that this is the last rewrite rule that will be processed for this request, which in this case I doubt is what you want. If there are rewrite rules further down for /en/stats.php they wont be processed.

mod_rewrite rule breaks when adding trailing slash 2 subdirectories deep

I'm very, very new to mod rewrite rules, and having trouble with one I'm using to redirect a site previously hosted in a subdirectory to a new domain. Here's the rule I'm using:
RewriteEngine on
RewriteBase /oldsite/ #also tried this without the trailing slash
RewriteRule ^.* http://newsite.com [R=301,NC,L]
This works perfectly until you get 3 levels deep and add a trailing slash to the redirected url. So, the results look like this:
olddomain.com/oldsite redirects to newsite.com [CORRECT]
olddomain.com/oldsite/ redirects to newsite.com [CORRECT]
olddomain.com/oldsite/subdirectory redirects to newsite.com/subdirectory [CORRECT]
olddomain.com/oldsite/subdirectory/ redirects to newsite.com [INCORRECT!]
I feel like I'm 99% there, but pulling my hair out a bit figuring out that last little bit. Any idea what I need to change?
Thanks!
Also, I tested placing the .htaccess file in the public html folder as well as in the /oldsite folder and there are no other htaccess files elsewhere on the site.
You're almost there, put this in the .htaccess in /oldsite on your server:
RewriteEngine On
RewriteRule (^.*) http://newsite.com/$1 [R=301,NC,L]
When you put the regex to match in parenthesis, it becomes available to use as $1. If you have more than one, $1 is the first, $2 the second, etc.
I suggest reading the manual page for mod_rewrite, specifically the rewriterule section (http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewriterule).

Rewrite doesn't work without trailing slash

I have problems getting an URL to work WITHOUT entering trailing slash.
It's:
www.domain.com/shop/buy/products/show/range/
.htaccess Rewrite Rule is:
RewriteRule ^shop/buy/([A-Za-z0-9]+)/show/([A-Za-z0-9\-\,]+)/?$ _shop/products.php?trg=${productmap:$1}&range=$2 [L]
It works with trailing slash (which I don't want in the URL) but not without. I should also add that if I was to remove '/show/' from the URL (which I can't do though), it works without trailing slash, or if 'range' contains a dash '-', as in 'new-product', it also works.
However, this URL works with or without trailing slash:
www.domain.com/shop/buy/products/show/range/color
.htaccess Rewrite Rule for this URL is:
RewriteRule ^shop/buy/([A-Za-z0-9]+)/show/([A-Za-z0-9\-\,]+)/([A-Za-z0-9\-\,]+)/?$ _shop/products.php?trg=${productmap:$1}&range=$2&color=$3 [L]
How can I get the first URL to work without trailing slash? This might be something really obvious as I'm a recent newbie to using .htaccess but I have now spent hours staring at the code and reading forum posts about rewrites but not been able to resolve this. Thank you!
T'm not so sure, but have You try to put /? in braces: (/)?, I think this will work:
RewriteRule ^shop/buy/([A-Za-z0-9]+)/show/([A-Za-z0-9\-\,]+)([/]?)$ _shop/products.php?trg=${productmap:$1}&range=$2 [L]
You Can Test This Code
Options +FollowSymLinks -MultiViews
RewriteEngine On
RewriteBase /
RewriteRule ^shop/buy/(.*?)/show/(.*)/(.*)$ _shop/products.php?trg=$1&range=$2&color=$3 [S,L,QSA]
RewriteRule ^shop/buy/(.*?)/show/(.*)$ _shop/products.php?trg=$1&range=$2 [S,L,QSA]
sample:
www.domain.com/shop/buy/products/show/range/
www.domain.com/shop/buy/products/show/range
redirect to:
www.domain.com/_shop/products.php?trg=products&range=range
and:
www.domain.com/shop/buy/products/show/range/color
www.domain.com/shop/buy/products/show/range/color/
redirect to:
www.domain.com/_shop/products.php?trg=products&range=range&color=color
one Another way is you Can Use Only This code
RewriteRule ^shop/buy/(.*?)/show/(.*)$ _shop/products.php?trg=$1&range=$2 [L,QSA]
after That split range in php By
list($range,$coler)=explode("/",$_GET['range']);
It is work too.

mod_rewrite rules not working as expected

I am using the following code
RewriteEngine on
RewriteRule ^/(certain|folders|on|server) - [NC,L]
RewriteRule (.*) http://newserver/blog$1 [L,NS]
I would expect it to ignore my list of folders, and redirect to everything else. Instead, it seems to always be redirecting to "newserver". Changing the "-" to a URL in the first statement does work, but I don't actually want those folders directed anywhere.
Why does my statement not work as expected?
Also, I have noticed that for all the folders not listed, I have "newserver/", while the ones I listed are just "newserver" (no uri)
You need to remove the leading slash in your rule. Rewrite rules in an htaccess file are given a URI to match against with the leading slash stripped off. Change your first rule by adding a ? after the slash:
RewriteRule ^/?(certain|folders|on|server) - [NC,L]
Or you can change it into a condition:
RewriteCond %{REQUEST_URI} !^/(certain|folders|on|server)
that will be applied to the rule that follows it.
Turns out my rules do work as expected. I was previously trying using these rules in apache.conf. Moving it to the sites "VirtualDirectory" tag seemed to do the trick

Resources