Trouble with htaccess mod_rewrite and directories - .htaccess

I've read dozens of posts about similar problems, but I can't get this one figured out.
I have SEO friendly URL's on my site that look like this...
http://www.website.com/tequila/bottle-name.html
http://www.website.com/whiskey/bottle-name.html
http://www.website.com/vodka/bottle-name.html
...where bottle-name is the actual name of the bottle.
I am doing a mod_rewrite to a PHP handler to actually deliver the pages. Each handler is located in each directory (tequila, vodka, whiskey).
The first one (tequila) is working, but the other two are not and I can't figure out why.
Here is the mod_rewrite code I have right now...
#Rewrite seo urls
RewriteCond %{REQUEST_URI} !^/tequila/
#RewriteCond %{REQUEST_FILENAME} !-f
#RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)\.html$ index.php?liquor=$1&liquor-type=tequila [L]
RewriteCond %{REQUEST_URI} !^/whiskey/
#RewriteCond %{REQUEST_FILENAME} !-f
#RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)\.html$ index.php?liquor=$1&liquor-type=whiskey [L]
RewriteCond %{REQUEST_URI} !^/vodka/
#RewriteCond %{REQUEST_FILENAME} !-f
#RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)\.html$ index.php?liquor=$1&liquor-type=vodka [L]
What appears to be happening is the whiskey and vodka pages are getting caught and processed by the tequila mod_rewrite (guessing because it is first in the list here).
So, http://www.website.com/vodka/vodka-bottle.html is actually getting rewritten as http://www.website.com/tequila/index.php?liquor=vodka-bottle.html&liquor-type=tequila.
It seems like I haven't setup the RewriteCond %{REQUEST_URI} !^/tequila/ correctly?
Any help or pointers anyone can provide are greatly appreciated!

Why are you negating the ^/tequila/? The ! will cause a match on all other liquor types, rather than the one you list.

Related

Rewrite multiple url's with htaccess

I'm struggling with this problem a few weeks now. In Google Search Console I get many crawl errors with the same problem: Google cannot find url's that don't even exist.
I've looked in the html-code, but the relative url's are all fine. And I'm using the /-base for all my internal links. I think the problem is my .htaccess file.
On my website nationsleaguevoetbal.nl I have two url's with different rewrites:
/nieuws/item
/wedstrijd/id/land
'land' isn't used and is only for looking nice. Now Google Search Console can't find for example:
/wedstrijd/id/nieuws/item
It combines the two url's where it shouldn't.
My .htaccess rewrite looks like:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)$ /index.php?pagina=$1 [QSA,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^nieuws/([^/]+)$ /index.php?pagina=nieuws&item=$1 [QSA,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^wedstrijd/([^/]+)/([^/]+)$ /index.php pagina=wedstrijd&id=$1&landen=$2 [QSA,L]
I thought the QSA would solve the problem, but the errors are coming back. Can you help me please?
Have it this way:
RewriteEngine On
# skip all files and directories from rewrites
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^nieuws/([^/]+)/?$ index.php?pagina=nieuws&item=$1 [QSA,L,NC]
RewriteRule ^wedstrijd/([^/]+)/([^/]+)/?$ index.php?pagina=wedstrijd&id=$1&landen=$2 [QSA,L,NC]
RewriteRule ^(.+?)/?$ index.php?pagina=$1 [QSA,L]

How to rewrite two GET values on htaccess and mod-rewrite

I just want to make the GET information that I sent:
http://mywebsite.com/folder/index.php?category=category-alias-here
http://mywebsite.com/folder/index.php?category=category-alias-here&page=5
To be rewrited on the URL bar as:
http://mywebsite.com/folder/category-alias-here/
http://mywebsite.com/folder/category-alias-here/5/
And I cant. Its very simple, I saw several similar questions. Tested several examples on stackoverflow and they all give me 404 for both category and both pages.
Here is a code that I tested:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)$ index.php?category=$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+)$ index.php?category=$1&page=$2 [L]
I understand that this code be wrong for my structure specifically, I tried several changes placing and removing ([^/]+) or changed the fist [L] to [N]. And several other things. But no luck with that.
Please notice, the whole website is inside a real directory (/folder/) and the .htaccess is also there (its not on root), once I launch the website everything will be on public_html, but I do not think this is the reason of this issue.
And yes, mod_rewrite is on. There is actually a .htaccess that I use, it works anywhere I place and it gets the category correctly but it is a bit messy.
Found a solution:
Options -Indexes
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^([a-z-]+)\/([0-9-]+)\/$ index.php?category=$1&page=$2 [NC,L]
RewriteRule ^([a-z0-9-]+)\/$ index.php?category=$1&page=$2 [NC,L]

Need to rewrite parameters AND redirect with htaccess

I need to simultaneously do two things with htaccess.
I need to take a URL like:
http://client.example.com/123
and rewrite the directory to a param, and simultaneously add another subdomain to the url so it looks like this:
http://client.qa.example.com/?param=123
This does the param bit correctly, but I can't figure out how to add the subdir:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^/[^/]+/?$
RewriteRule ^([^/]*)/?$ /?param=$1 [L]
You can examine the host header using a RewriteCond and extract the relevant parts of the name. Use them in the rewrite. Back references to matches in RewriteConds appear as %n
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{HTTP_HOST} (.+?)\.(.*)
RewriteRule ^([^/]*)/?$ http://%1.qa.%2/?param=$1 [R,L]
(.+?)\.(.*) will do a match on everything up to the first . and then everything to the end. So client and example.com will respectively be in %1 and %2
If your .htaccess is in the root of client.example.com, it should be a simple redirect. Of course the directory has to be a fake directory or this won't redirect.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/?$ http://client.qa.example.com/?param=$1 [R=301,QSA,L]
You can use the following to match (check for htaccess syntax):
(http://[^.]+\.)([^/]+/)([^/]*)/?$
And replace with:
$1qa.$2?param=$3
See DEMO
Finally got it working using:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{HTTP_HOST} (.+?)\.(.*)
RewriteRule ^([^/]*)/?$ http://%1.qa.%2/?param=$1 [R,L]
Now I just have to figure out how to work in 2 parameters, given that param 2 isn't always going to be present.

rewrite url to root directory with url cutting

I have such urls:
http://site.ru/ontent/wefwefw/article.php?article=369-tayskaya-kuhnya-recept-s-foto
http://site.ru/ontent/wefwefw/article.php?article=32237-ogurci-recepti-na-zimu
http://site.ru/ontent/wefwefw/article.php?article=90-ogurci-na-zimu-recepti-po-koreyski
I want to rewrite tham like:
http://site.ru/tayskaya-kuhnya-recept-s-foto.html
http://site.ru/ogurci-recepti-na-zimu.html
I tried smth like:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ ontent/wefwefw/$1 [L]
But how cut unnecessary parts of string?
Unless article.php is able to derive the right article from the title alone, what you want to do is not possible. mod_rewrite is good at rewriting things, but it can't summon an article-id from thin air if it isn't in the original request. You would have something like:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]+)\.html$ ontent/wefwefw/article.php?article=$1 [L]
When you would request http://site.ru/tayskaya-kuhnya-recept-s-foto.html, it will load http://site.ru/ontent/wefwefw/article.php?article=tayskaya-kuhnya-recept-s-foto. Then you have to get the id 369 in some other way based on the title if needed.
The best in this case is:
http://site.ru/369-tayskaya-kuhnya-recept-s-foto.html
redirect to
http://site.ru/ontent/wefwefw/article.php?article=369
with:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(\d+)-[^/]*\.html$ ontent/wefwefw/article.php?article=$1 [L]

.htaccess do something else if file not exist

We are using an .htaccess in combination with anchor tags to serve files and conceal the server directory structure.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /_docu/clients/$1/$2/$3.pdf [NC,L]
For example, all files are stored under /public_html/_docu/clients/ and inside that folder are listed all the clients, and then under each client their projects. However, an anchor tag for a file would read only:
http://mydomain.com/client-name/proj-name/docname.pdf
(the /_docu/clients/ being omitted - there is a good reason for this). The above .htaccess grabs the client-name, proj-name and docname and serves it from the correct folder:
http://mydomain.com/_docu/clients/client-name/proj-name/docname.pdf
whilst preserving in the address bar the incorrect (concealed) directory structure.
I wish to handle the error condition of a document not existing. This should never happen, but it could. Can anyone suggest a way of dealing with this? Can something functionally akin to "if fileexist($1/$2/%3.pdf)" be somehow constructed in an .htaccess file?
EDIT:
Delayed response as JL's answer below required research and experimentation. Thanks, Jon, for the gentle push in the right direction but I haven't got it to work just yet. Here's what I tried:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# check if the requested file exists in the "_docu/clients" directory
RewriteCond %{DOCUMENT_ROOT}/_docu/clients/$1/$2/$3.pdf -f
RewriteRule ^([a-z0-9])/([a-z0-9])/([a-z0-9]*).pdf$ /_docu/clients/$1/$2/$3.pdf [NC,L]
RewriteRule ^(.*)$ /errors/404.php [L]
I thought that what that should do is:
If http://mydomain.com/_docu/clients/$1/$2/$3.pdf does not exist,
GoTo page http://mydomain.com/errors/404.php
Actual outcome is an "internal server error" message.
EDIT TWO:
Latest changes:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^/([a-z0-9])/([a-z0-9])/([a-z0-9]*).pdf$
RewriteCond %{DOCUMENT_ROOT}/_data/cli/%1/%2/%3.pdf -f
RewriteRule ^([a-z0-9])/([a-z0-9])/([a-z0-9]*).pdf$ /_data/cli/$1/$2/$3.pdf [NC,L]
RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteRule ^(.*)$ /metshare/404.php [L]
The problem with this one is that legitimate pages also are directed to 404.php
MESSAGE TO FUTURE READERS:
All of the above concerns were addressed in Jon Lin's final answer. As issues were detected, he modified his answer until it was a perfect, working solution. I am leaving the above as it is because there are some good ULOs within (unscheduled learning opportunities) for those who want to compare versions.
You need to use a condition like this:
RewriteCond %{DOCUMENT_ROOT}/_docu/clients%{REQUEST_URI} -f
So that your rules looks ssomething like:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# check if the requested file exists in the "_docu/clients" directory
RewriteCond %{DOCUMENT_ROOT}/_docu/clients%{REQUEST_URI} -f
RewriteRule ^ /_docu/clients%{REQUEST_URI} [L]
EDIT: Response to edit in question
You can't do this:
RewriteCond %{DOCUMENT_ROOT}/_docu/clients/$1/$2/$3.pdf -f
Because the backreferences for $1/$2/$3 don't exist yet, they are matched in the groupings in your RewriteRule, which hasn't happened yet at this point. But you can try something like this:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# check if the requested file exists in the "_docu/clients" directory
RewriteCond %{REQUEST_URI} ^/([a-z0-9])/([a-z0-9])/([a-z0-9]*).pdf$
RewriteCond %{DOCUMENT_ROOT}/_docu/clients/%1/%2/%3.pdf -f
RewriteRule ^([a-z0-9])/([a-z0-9])/([a-z0-9]*).pdf$ /_docu/clients/$1/$2/$3.pdf [NC,L]
RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /errors/404.php [L]
Essentially creating a match against %{REQUEST_URI} in a previous RewriteCond then using the %N backreferences in the following RewriteCond.

Resources