.htaccess rewrite only files in a certain directory - apache

I found this question which is similar to my request here, but I'm not sure how to modify it to my need
I want to ...
a) Drop the directory (edited, forgot to mention)
Note, I'm just using the directory as a container to keep this rule
separate from affecting other files. Maybe there's a better way to
work with a range of files only, such as a specific string in the
file name? Directory seemed like the simplest solution.)
b) Drop the file extension
c) Replace it with a trailing slash
... on files contained only within the /categories/ directory
So the effect is that website.com/categories/My-File-Name.php becomes website.com/My-File-Name/
This is what I've tried so far:
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/categories/$
RewriteRule ^([^\.]+)/$ /categories/$1.php [NC,L]

This should work:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/categories/$1.php -f
RewriteRule ^(.+?)/?$ /categories/$1.php [L]

Related

Rewrite files with certain extension to a specific directory

So... I have a few million PNGs with unique names spread across a complicated structure of directories that goes 15-20 levels deep, and I want to move them into a directory /my/special/directory/
I can't figure out a way to do this with rewrites (not redirects)
I have tried:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/\.]+).png?$ /my/special/directory/$1.png [R]
But this works on the first level only (root). I have also tried
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([a-zA-Z0-9/]+)([^/\.]+).png?$ /my/special/directory/$2.png [R]
But it doesn't work at all. How should I write this?
I am checking for the image not to exist because there are other directories in this vhost that contain images and will remain as they are.
TIA
I don't really understand that pattern you try: ^([^/\.]+).png?$...
Why the ? at the end? And why the explicity denial of dots in file names? The reason this only works for "the first level" certainly is that you explicitly deny acceptance of paths with contained / which happens to be the folder delimiter...
Also just use [L] instead of [R] since you do not want a redirection.
This gives us:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)\.png$ /my/special/directory/$1.png [L]
In case you have to rewrite such that only the file name is captured (depends on the structure of your links, actually), this would probably be a good start:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule /?([^/]+)\.png$ /my/special/directory/$1.png [L]
Note: there is no leading ^ in the second variant, since you are not interested in what path is specified before the last folder separator...

.htaccess excluding directory issue

I have a website consisting of a single index.html file. I have several menus, and need to go 3 levels deep, so I want a php-like structure as such: index.html?main=$1&secondary=$2&tertiary=&3. This has to be reduced to www.example.com/$1/$2/$3. Overall pretty simple I would think, using following rules for in .htaccess:
RewriteRule ^([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)?$ index.html?main=$1&secondary=$2&tertiary=$3
RewriteRule ^([A-Za-z0-9-]+)/([A-Za-z0-9-]+)?$ index.html?main=$1&secondary=$2
RewriteRule ^([A-Za-z0-9-]+)?$ index.html?main=$1
Now, I also have several folders in my root folder that shouldn't be affected, otherwise my include's wont work. Looking at this answer I've already tried exluding these folders using RewriteRule ^(bower_components|photos)($|/) - [L] before the other rules, but it didn't work. I've also tried this answer, making a .htaccess with contens RewriteEngine Off and putting it in my folders, also without success. So obviously I'm doing something wrong somewhere. To show my folder layout, here's a quick snapshot of it:
Here's my current .htaccess file:
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .* - [L]
RewriteRule ^([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)?$ index.html?main=$1&secondary=$2&tertiary=$3
RewriteRule ^([A-Za-z0-9-]+)/([A-Za-z0-9-]+)?$ index.html?main=$1&secondary=$2
RewriteRule ^([A-Za-z0-9-]+)?$ index.html?main=$1
Now, if I go to http://localhost/myProject/activities, so 1 level deep as the index.html file is located in myProject, it does work and all includes are included correctly. However, when going to http://localhost/myProject/activities/test, I get to the basic index.html page, but my includes point to http://localhost/myProject/activities/bower_components/platform/platform.js, so the activities is too much.
Keep your rules like this:
Options +FollowSymLinks
RewriteEngine On
RewriteBase /myProject/
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .* - [L]
RewriteRule ^([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/?$ index.html?main=$1&secondary=$2&tertiary=$3 [L,QSA]
RewriteRule ^([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/?$ index.html?main=$1&secondary=$2 [L,QSA]
RewriteRule ^([A-Za-z0-9-]+)/?$ index.html?main=$1 [L,QSA]
Then for css/js/image inclusion just use absolute path in your css, js, images files rather than a relative one. Which means you have to make sure path of these files start either with http:// or a slash /.
You can also try adding this in your page's HTML header: <base href="/myProject/" /> so that every relative URL is resolved from that URL and not the current URL.

.htaccess display /base1/folder/ using the content of /base2/folder.html

When I open the url http://mysite.com/base1/folder/, I want it to display the contents of http://mysite.com/base2/folder.html. There is an index.html file in the folder folder.
To be clearer, the html file folder.html resides in the folder base2.
My .htaccess file does not work as expected
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/base1/([^/]+)/(.+)$ /base2/$1.html [L]
Could anyone please tell me is wrong with my .htaccess file?
Thanks!
Your regular expression looks wrong:
^/base1/([^/]+)/(.+)$
^^^ requires one or more characters
This should work (to accept anything following /folder/)
^/base1/([^/]+)/
Or this (to accept only /folder/)
^/base1/([^/]+)/$
Furthermore I would remove the two RewriteCond as your rule. (Though they shouldn't do any harm if /base1/ doesn't exist)

Redirecting via .htaccess to .php with arguments in current folder

I'm trying to redirect something like foo/bar to ?foo=bar, so I can do www.mydomain.com/hey/foo/bar to www.mydomain.com/hey/?foo=bar, but I can't seem to get the syntax right. I tried the following:
RewriteEngine on
RewriteRule ^foo/(.*)$ ?foo=bar [NC]
But this doesn't work. How would I accomplish this? I tried adding a forward slash behind the question mark, but that makes it link to the root directory.
Thanks,
Jengerer
You need to include the actual file you're rewriting to. Using ?foo=bar isn't pointing at any file in particular.
Use the following rule:
RewriteEngine on
RewriteRule ^(.*)/(.*)$ index.php?$1=$2 [NC]
Notice that I'm pointing to the file index.php. $1 is replaced by whatever is matched by the first (.*) and $2 by the second. So, if someone browsed to foo/bar, they would be taken to index.php?foo=bar.
Important Note: If you choose to use (.*) and accept any character for the variable name or value and plan to use this information in database queries, you'll want to be certain to escape this content properly using your database's escape functions (mysql_real_escape_string or pg_escape_string) or by using prepared statements.
If you're having problems with style or elements on the page not showing correct because you're using relative paths, you'll need to use absolute paths starting at the root. Otherwise, your pages style, images, etc. would break.
<link rel="stylesheet" type="text/css" href="/path/to/style.css" />
Maybe try removing the ^ from ^foo/(.*)$?
Well, it turns out that the problem wasn't in the redirection, but in the links that were made after the redirection.
After redirecting from /foo/bar to /?foo=bar, the CSS links and images were poorly matched because it was now looking for local links within the /foo/bar directory, which doesn't exist. What an interesting 'glitch'.
When you place the .htaccess in your root it should be like this:
RewriteEngine on
RewriteCond %{REQUEST_URI} !^$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\/]+)\/([^\/]+)\/([^\/]+)$ $1?$2=$3 [L]
when you place the .htaccess in your "hey" folder, it should be like this:
RewriteEngine on
RewriteCond %{REQUEST_URI} !^$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^\/]+)\/([^\/]+)$ ?$1=$2 [L]

RewriteRule checking file in rewriten file path exists

How can you use ModRewrite to check if a cache file exists, and if it does, rewrite to the cache file and otherwise rewrite to a dynamic file.
For example I have the following folder structure:
pages.php
cache/
pages/
1.html
2.html
textToo.html
etc.
How would you setup the RewriteRules for this so request can be send like this:
example.com/pages/1
And if the cache file exists rewrite tot the cache file, and if the cache file does not exists, rewrite to pages.php?p=1
It should be something like this: (note that this does not work, otherwise I would not have asked this)
RewriteRule ^pages/([^/\.]+) cache/pages/$1.html [NC,QSA]
RewriteCond %{REQUEST_FILENAME} -f [NC,OR]
RewriteCond %{REQUEST_FILENAME} -d [NC]
RewriteRule cache/pages/([^/\.]+).html pages.php?p=$1 [NC,QSA,L]
I can off coarse do this using PHP but I thought it had to be possible using mod_rewrite.
RewriteRule ^pages/([^/\.]+) cache/pages/$1.html [NC,QSA]
# At this point, we would have already re-written pages/4 to cache/pages/4.html
RewriteCond %{REQUEST_FILENAME} !-f
# If the above RewriteCond succeeded, we don't have a cache, so rewrite to
# the pages.php URI, otherwise we fall off the end and go with the
# cache/pages/4.html
RewriteRule ^cache/pages/([^/\.]+).html pages.php?p=$1 [NC,QSA,L]
Turning off MultiViews is crucial (if you have them enabled) as well.
Options -MultiViews
Otherwise the initial request (/pages/...) will get automatically converted to /pages.php before mod_rewrite kicks in. You can also just rename pages.php to something else (and update the last rewrite rule as well) to avoid the MultiViews conflict.
Edit: I initially included RewriteCond ... !-d but it is extraneous.
Another approach would be to first look if there is a chached representation available:
RewriteCond %{DOCUMENT_ROOT}/cache/$0 -f
RewriteRule ^pages/[^/\.]+$ cache/$0.html [L,QSA]
RewriteRule ^pages/([^/\.]+)$ pages.php?p=$1 [L,QSA]
To generalize the question: insert this above the rule that should not be matched if the file exists.
RewriteCond %{REQUEST_FILENAME} !-f
Sean Bright's answer provides a nice worked example for the caching question, but this line works more broadly. In my case, I have a link shortener where people can choose custom URLs and I didn't want it to be able to override existing files such as favicon.ico. Adding this line before the rewriterule fixed that issue.