htaccess infinite redirect - .htaccess

I'm working on a legacy codebase, with three different folders of images. An image could be in any one of the three folders, in a pretty much random manner.
I initially attempted to check for file existence within PHP; however, images are being displayed in tons of places, and I'm hoping I can just achieve the same thing with an htaccess file. However, so far no luck.
Here's what I've got so far:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^Folder_1/(.*)$ Folder_2/$1 [L,NC]
RewriteRule ^Folder_2/(.*)$ Folder_3/$1 [L,NC]
What I'd like to happen is for any image request that doesn't exist, check the other two folders, in any order, for its existence. So, if someone requests Folder_3/image.png, it'll check Folder_1/image.png, then Folder_2/image.png
Any suggestions for how to write the htaccess file?

Use the [N] flag to start rewriting from the top again.

In case you weren't able to get it to work based on Ignacio's suggestion, I'd suggest something like this, which, although a bit convoluted, seems to work:
RewriteEngine on
# If the request points to a real resource, just end here
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -l
RewriteRule ^ - [L]
# Check the other two directories
# First, figure out which directory we're currently in and capture the rest
RewriteCond $1|Folder_1|Folder_2|Folder_3 ^([^\|]+)\|(.*?)\|?\1\|?(.*)$
# Now break them up into two folders
RewriteCond %2|%3 ([^\|]+)\|([^\|]+)
# Check the first alternate folder to see if it exists there
RewriteCond %{DOCUMENT_ROOT}/%1/$2 -f [OR]
# If not, make the second option move to the first back reference
RewriteCond %2 ^(.*)$
# Check the second alternate folder to see if it exists there
# (or check the first option again if it succeeded..we could condition
# this out in that case, but I don't know if it's worth adding)
RewriteCond %{DOCUMENT_ROOT}/%1/$2 -f
# If so rewrite to the correct alternate folder
RewriteRule ^([^/]+)/(.*)$ /%1/$2

A RewriteCond directive does only belong to the very next RewriteRule directive. That means you would need to place these RewriteCond directives in front of each RewriteRule:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^Folder_1/(.+) Folder_2/$1 [L,NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^Folder_2/(.+) Folder_3/$1 [L,NC]
By the way: Your second condition %{REQUEST_FILENAME} !-d is probably useless as it only tests for an existing directory.

Related

How to mod_write query param to path for arbitrarily long path?

I'm building a simple API with apache and I want to map /really/long/path/api/captions.php?caption_id=blah to /really/long/path/api/captions/blah. It's important to NOT have to specify a full path in the rewrite rule because I want this to work no matter where I deploy this code to. However, I can't find/figure out a working example of .htaccess rewrite rules that enable me to match based upon only the final part of the extension.
So, assuming that I have, say, captions.php in a dir called api, what .htaccess file do I need to include in api to accomplish this transform without having /really/long/path/ anywhere therein?
(I also want to be able to map /really/long/path/api/captions.php to /really/long/path/api/captions/ and /really/long/path/api/captions.)
I've tried all sorts of wildcard-like syntax; here's one of those non-working attempts:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*?)/?captions/(.*?)/?$ /captions.php?caption_id=$1 [L]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /captions\.php\?caption_id=([^\&\ ]+)
RewriteRule ^(.*?)/?captions\.php$ /captions/%1? [L,R=301]
Thanks!
Got there in the end. This is all that was needed:
RewriteEngine On # Turn on the rewriting engine
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^captions/?$ captions.php [NC,L]
RewriteRule ^captions/(.*)/?$ captions.php?caption_id=$1 [NC,L]

Multiple rewrite conditions for multiple parameters

There is an issue with the htaccess rewrite conditions in my setup.
Currently I have the following code.
Options +FollowSymLinks
RewriteEngine on
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ http://mydom.com/$1.php
This works fine for any base page making them look like this.
http://mydom.com/page
What I want to also be able to do is add parameters from the url if they exist. I have some pages that will be like this.
http://mydom.com/page?param=1&secondParam=2
What I've tried to do is add this.
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/(.*)/(.*)$ http://mydom/$1/$2/$3 [L]
RewriteRule ^(.*)/(.*)$ http://mydom/$1/$2 [L]
This made sense to me, because I thought if the condition didn't match, it would move on, but this gave me an internal server error.
What I ended up doing was setting up a separate rule for each page that could have multiple parameters like this.
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^page/(.)/(.)$ http://mydom.com/page.php?param=$1&secondParam=$2 [L]
RewriteRule ^page/(.*)$ http://mydom.com/page.php?param=$1 [L]
RewriteRule ^(.*)$ http://mydom.com/$1.php
This works, however you need to keep in mind relative links you may have in your site such as style sheets and javascript files. In my case, I had to replace all relative paths with full site paths, depending on the way you set up your site, it could take a while to replace.

Simple .htaccess rewrite for _get variable

I am working on a site that uses pages with _get variables for example you can get to www.thewebsite.com/users.php?uservar=username by just using www.thewebsite.com/users/username.
The issue I run into is when I also try to add in url rewrites that also cut off file extenuation so aboutus.php becomes about us.
Can I have these two functions in one .htaccess file?
I tried this but it did not seem to work well
RewriteEngine on
RewriteRule ^([^/\.]+)/?$ /user.php?page=$1 [L]
You can have both at the same time, but you need the routing rule (the one that targets user.php) to be below the rule that tries to re-attach the extension. So something like this:
# whatever rule you have to re-attach the extension:
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*)$ /$1.php [L]
# now your user routing rule, make sure you add the condition:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/\.]+)/?$ /user.php?page=$1 [L]

Excluding a script from the general UrlRewrite rules

I have following rewrite rules for a website:
RewriteEngine On
# Stop reading config files
RewriteCond %{REQUEST_FILENAME} .*/web.config$ [NC,OR]
RewriteCond %{REQUEST_FILENAME} .*/\.htaccess$ [NC]
RewriteRule ^(.+)$ - [F]
# Rewrite to url
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !^(/bilder_losning/|/bilder/|/gfx/|/js/|/css/|/doc/).*
RewriteRule ^(.+)$ index.cfm?smartLinkKey=%{REQUEST_URI} [L]
Now I have to exclude a script including its eventually querystrings from the above rules, so that I can access and execute it on the normal way, at the moment the whole url is being ignored and forwarded to the index page.
I need to have access to the script shoplink.cfm in the root which takes variables tduid and url (shoplink.cfm?tduid=1&url=)
I have tried to resolve it using this:
# maybe?:
RewriteRule !(^/shoplink.cfm [QSA]
but to be honest, I have not much of a clue of urlrewriting and have no idea what I am supposed to write. I just know that above will generate a nice 500 error.
I have been looking around a lot on stackoverflow and other websites on the same subject, but all I see is people trying to exclude directories, not files. In the worst case I could add the script to a seperate directory and exclude the directory from the rewriterules, but rather not since the script should really remain in the root.
Just also tried:
RewriteRule ^/shoplink.cfm$ $0 [L]
but that didn't do anything either.
Anyone who can help me out on this subject?
Thanks in advance.
Steven Esser
ColdFusion programmer
Please try to put the following line at the top of your config (after RewriteEngine on):
RewriteRule ^shoplink.cfm$ - [L]

htaccess rewriterule

A fairly basic htaccess question, but I don't use it much, so i have no idea.
I want to check if the requested file exists. If it does, forward to one page, and if not forward to another page and pass the requested path as GET.
Thanks in advance.
RewriteEngine On
# check if requested file or directory exists
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
# if not, pass it to index.php
RewriteRule ^(.*) index.php?page=$1 [QSA]
As Gumbo suggested, you can repeat the condition without the ! if you also want to rewrite the URL when a file exists. Maybe you want to 'protect' your real files and folders with this method.
Use the -f expression in a RewriteCond condition to test if the given path points to an existing regular file:
RewriteEngin on
# file exists
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ one-page [L]
# file does not exist
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ another-page [L]
The initial requested URI should then be available in an environment variable.

Resources