htaccess and folders does it affect? - apache

i have folders and another php files with an id.
What i want to do is to be able to view those php files in the following format: www.website.com/cakedetails in the browser url and site-wide rather than www.website.com/cakes.php?id=chocolate-cake
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
RewriteRule ^http://www.%{HTTP_HOST}/([a-z.*0-9_-]+)/$ http://www.%{HTTP_HOST}/cakes.php?id=$1
i managed to put the above in my htaccess file, but so far to no avail. the first part of the code converts to www. if it does not have that prefix, and the second part of the code to gather the cake details.
Can you tell me if the above code is correct, as im no expert in htaccess language and i cannot get the above code to work.
Your input is welcome :)

You can't have stuff like this: http://www.%{HTTP_HOST}/ in your rule's regex. The string that the regex matches against doesn't include the protocol/domain name, just the URI, so just the /cakedetails part.
Problem with that is you don't want to blindly match everything, so you need some conditions to make sure someone's not requesting an existing file.
Try:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)$ /cakes.php?id=$1 [L,QSA]

Related

How to I replace a part of the URL string containing a query using htaccess?

I have a URL string using a PHP query string.
I want to make the URL pretty, but I haven't been able to make the rule properly.
Currently the URL looks like this:
http://localhost/pages/map?name=Skyfall-2022
But I want it to look like this:
http://localhost/pages/Skyfall-2022
This is my current htaccess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.php [NC,L]
RewriteRule ^([^\.]+)$ $1.html [NC,L]
RewriteRule ^pages/(.+)$ /pages/map?name=$1
I get a 500 Internal Error with this when I try to type in the desired URL. I don't really understand Regular Expressions so I would appreciate if someone could adjust this for me with an updated .htacces
With your shown samples, please try following htaccess rules.
Please make sure to clear your browser cache before testing your URLs.
RewriteEngine ON
##External redirect for url change in browser rules here...
RewriteCond %{THE_REQUEST} \s/(pages)/map/?\?name=(\S+)\s [NC]
RewriteRule ^ %1/%2? [R=301,L]
##Internal rewrite here for internal file's serving here.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]*)/(.*)/?$ $1/all-maps.php?name=$2 [QSA,L]
NOTE: I have mentioned map? in rewrite rules(2nd set of rules written in comments also in rules), you can change it with your php file's name whatever php file you have to pass query string to.
NOTE2(OP's fixes as per OP environment): tweaked 1 rule a
bit to $1/all-maps.php?name=$2 to $1/map.php?name=$2 and moved the all-maps.php one directory down and these rules worked fine, mentioned by OP in comments here. Just sharing here, in future it could help people that apart from above rules this was done as part of solution.

Why does the following file does not exist condition not work in htaccess?

Don't know why the following rewrite rules do not work. The file-not-exist condition always triggers even though the file article/1.html file does exist. The requested URL is:
https://exampledomain.com/test-a-1.html
RewriteCond %{REQUEST_FILENAME} ^(.*)-a-([0123456789_]*)\.html$
RewriteCond %{DOCUMENT_ROOT}/article/%2.html !-f [NC,OR]
RewriteCond %{QUERY_STRING} !^$
RewriteRule ^(.*)-a-([0123456789_]*)\.html$ news.php?article=$2&%{QUERY_STRING}
RewriteRule ^(.*)-a-([0123456789_]*)\.html$ /article/$2.html
If I comment out the !-f RewriteCond it nicely falls through to the second rule and accesses article/1.html. If this condition is active it never rewrites to article/1.html but always goes to news.php?article=1
With your shown samples, please try following. Please make sure to clear your browser cache before testing your URLs.
RewriteEngine ON
##Rules when .html file is not present in system.
RewriteCond %{DOCUMENT_ROOT}/article/$2.html !-f [NC]
RewriteRule ^([^-]*)-a-([0-9_]*)\.html/?$ news.php?article=$2&%{QUERY_STRING} [NC,L]
##Rules when .html file is present in system.
RewriteCond %{DOCUMENT_ROOT}/article/$2.html -f [NC]
RewriteRule ^([^-]*)-a-([0-9_]*)\.html/?$ article/$2.html [NC,L]
I finally figured out the answer to my question. There is nothing wrong with my rewrite conditions or rules. They are exactly what they should be. However, %{DOCUMENT_ROOT} does not point to where the Apache documentation says it points to. On my Ionos managed server it points to /var/www/html. However, my actual document root is something like /kunden/homepages/... So the solution is to use the actual absolute path rather than %{DOCUMENT_ROOT}. Now everything works as it should.

Remove part of the query string with mod_rewrite

I am not very good with .htaccess at all, so I want to achieve something very simple, but I can't. What I want to do is to redirect certain files to test.php, and if test is ok, PHP redirects back to original page. It works fine, I add the "test=ok" part to the original URL, that way I don't get a redirect loop. However, I want to remove the test=ok query part from the original URL on redirection. How can I achieve that???
TL/DR
I have several URLs I want rewritten through mod_rewrite.
examples:
http://example.com/?time=1&test=ok
http://example.com/?test=ok
How can I remove the &test=ok and the ?test=ok parts using .htaccess?
Right now I have:
RewriteCond %{QUERY_STRING} ^test=ok$ [NC]
RewriteRule (.*) /$1? [L]
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_URI} (/[^.]*|\.(php|html?|js))$ [NC]
RewriteCond %{QUERY_STRING} !test=ok [NC]
RewriteRule .* test.php [L]
But that doesn't remove the test=ok part... :(

RewriteCond Being Ignored?

I am trying to use mod_rewrite on a Ubuntu 12.04 server to make my URLs more readable, however I want to add an exception for images and css files.
My input URLs are in the format \controller\action which is then re-written to index.php?controller=controller&action=action. I want to add an exception so that if an image or css file is specified, the URL is not re-written, e.g. \images\image.jpg would not be re-written.
My .htaccess code is as follows:
RewriteEngine on
RewriteCond %{REQUEST_URI} !(\.gif|\.jpg|\.png|\.css)$ [NC]
RewriteRule ^([a-zA-z]+)/([a-zA-z]+)$ test.php?controller=$1&action=$2 [L]
RewriteRule ^([a-zA-z]+)/([a-zA-z]+)/([^/]*)$ test.php?controller=$1&action=$2&$3 [L]
My re-write code is working fine and the URLs are coming out as intended, however even if I request an image, the URL is still being re-written. It appears that my RewriteCond is being ignored, anyone any suggestions as to why this might be?
The RewriteCond only applies to your first RewriteRule, it should be reproduced for the second rule. However, I think that is better to add a non-rewriting rule, before, to exclude existing stuffs.
# Do nothing for files which physically exist
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .* - [L]
# your MVC rules
RewriteRule ^([a-zA-z]+)/([a-zA-z]+)$ test.php?controller=$1&action=$2 [L]
RewriteRule ^([a-zA-z]+)/([a-zA-z]+)/([^/]*)$ test.php?controller=$1&action=$2&$3 [L]
The rewriteCond rule is only applied for the next RewriteRule.
So you need to at least repeat the rewriteCond for your seconde RewriteRule.
No there is certainly better things to do.
For example a usual way of doing it is to test that the url is matching a real static ressource. If all your php code is outside the web directory (in libraries directory, except for index.php) then all styatic ressources available directly on the the document root can only be js files, css files, or image files.
So this is the usual way of doing it:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([a-zA-z]+)/([a-zA-z]+)$ test.php?controller=$1&action=$2 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([a-zA-z]+)/([a-zA-z]+)/([^/]*)$ test.php?controller=$1&action=$2&$3 [L]
But this is a starting point. We could certainly find something to avoid doing 2 rules for this (maybe I'll have a look later)

Is it possible to chain RewriteCond in htaccess?

I am going to be doing some basic %{HTTP_HOST} work in my .htaccess file and was wondering if it would be possible to do something similar to this:
RewriteCond %{HTTP_HOST} ((foo|bar|baz).com)$
RewriteCond %{DOCUMENT_ROOT}/apps/%1/webroot%{REQUEST_URI} -d [OR]
RewriteCond %{DOCUMENT_ROOT}/apps/%1/webroot%{REQUEST_URI} -f
RewriteRule %{DOCUMENT_ROOT}/apps/%1/webroot%{REQUEST_URI} [L]
RewriteRule ^(.*)$ index.php?uri=$1 [QSA,L]
basically, if someone visits foo.com on any sub-domain, I want them to be served files directly from that folder but also have any requests that aren't for specific files sent to my index.php file for processing (which will do the routing)
The reason I am asking is because what I have written above does not actually work, so is there a way to do it? (also if this SHOULD work then it'll obviously be a problem with the rest of my .htaccess file, but it all works when dealing with just one application folder)
The other (messy IMO) way would be to route everything to the folders and have a second .htaccess file for each domain, but I'd rather not do this if it can be done in one file!
Your first rewrite rule is missing a regex, which makes the rewrite engine thing you are trying to match (as a regular expression) %{DOCUMENT_ROOT}/apps/%1/webroot%{REQUEST_URI} and you want to rewrite that to [L]. I suspect you want that to look like:
RewriteRule ^ /apps/%1/webroot%{REQUEST_URI} [L]
The ^ matches anything, since you've already vetted the request with your 3 conditions.
Now you need to add a few conditions to your last rule so that it doesn't blindly get applied to everything. You probably want something like:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?uri=$1 [QSA,L]