mod_rewrite remapping folder - apache

I've currently updated our site, and the image folder name has changed from /img/ to /images/.
I'm still getting 404 errors in my apache error log from bots etc trying to access the old /img folder.
I'm trying to write a mod_rewrite rule to redirect any attempts to access /img/ to refer to /images/.
This is what I've got so far:
RewriteRule ^img/?(.*)$ images/$1 [R=301,L]
However, whenever I access http://mysite.com/img I still get my 404 page (instead of a forbidden page which I should receive for accessing /images).
Is this correct? I do have another rule forcing use of ssl if that matters.
Many thanks

This rule should be place on your root folder:
Options +FollowSymLinks -MultiViews
RewriteEngine On
RewriteBase /
RewriteCond %{DOCUMENT_ROOT}/images/$1 -d [OR]
RewriteCond %{DOCUMENT_ROOT}/images/$1 -f
RewriteRule ^img/(.*) /images/$1 [R=302,NC,L]
This rule will redirect only existent files or folders existent on http://domain.com/images.
Keep in mind that you may have been cached from previous attempts since you're using R=301, so to make sure its working try using a different browser.
Note that I am using R=302, to avoid this caching, once you confirm it is working, change it to R=301.

Related

How can I stop my .htaccess file from including the full file path when testing locally?

I've built a website which uses the url to load pages from a database. The traffic is redirected to the index.php file, which then queries the url and loads the appropriate page. To make this work I'm using some rewrite rules in the .htaccess file.
Although I have been able to make this work in a live environment, I'm struggling to make it work locally, using XAMPP.
I'm using the following rules:
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_URI} !.*\.png$ [NC]
# Various other exceptions
RewriteRule .* /index.php
Which are returning the following url
http://localhost/C:/xampp/htdocs/project-folder/localhost/project-folder/
but I'd like the following page to be loaded:
localhost/project-folder/index.php
I can't understand where/why the full file path is being included, nor how I can exclude it.
Can anyone help?

Hide public access to directories but allow through RewriteRule

I have the following structure:
public_html/
hidden_directory/
sub_folder/
sample_file.txt
other_file.txt
another_folder/
another_file.txt
My end goal is to have the contents of hidden_directory visible only through redirects. My first attempt at putting them outside the public_html was unsuccessful. Then I tried the structure you see above with a Redirect like
RewriteRule ^sub/(.*) hidden_directory/sub_folder/$1 [L]
to access through:
http://mysite/sub/sample_file.txt
And that worked great giving me the content I wanted from the file location and URL I wanted. But I didn't like that files were also available from:
http://mysite/hidden_directory/sub_folder/sample_file.txt
I did do a
deny from all
in hidden_directory, and that stopped direct access like I wanted, though it also broke the rewrites.
Is there any htaccess solution that I could have these files in a folder not directly accessible yet still reachable with rewrites?
Is there any htaccess solution that I could have these files in a folder not directly accessible yet still reachable with rewrites?
Yes use a rule based on THE_REQUEST variable to block direct access to hidden_directory:
RewriteEngine On
# block direct access to a given path
RewriteCond %{THE_REQUEST} \s/+hidden_directory[/?\s] [NC]
RewriteRule ^ - [F]
RewriteRule ^sub/(.*)$ hidden_directory/sub_folder/$1 [L,NC]
THE_REQUEST variable represents original request received by Apache from your browser and it doesn't get overwritten after execution of some rewrite rules. Example value of this variable is GET /index.php?id=123 HTTP/1.1

Sending access is denied error using htaccess on apache for all files but a certain one

I have a folder containing various .php files, and I want to prevent direct access to them, BUT to index.php.
This is what I got so far, and it appears working:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond $1 !^(index\.php)
RewriteRule ^(.*)$ /403.php/$1 [R=403]
</IfModule>
Is this the correct way to do it? Also note that 403.php doesn't actually exist among the files I have in the folder.
EDIT: to better clarify what I'm trying to do -- I have a folder (we can assume named "includes") containing an index.php file, and various other files which are included by index.php.
I don't want users / malicious bots / whoever to be able to directly access anything in "includes" other than index.php.
In case they reach anything else (regardless whether the file exists or not), I want to send to the browser a 403 - Access Denied HTTP response code.
The correct way is to use the F flag, which simply returns a 403 forbidden and you can use - as the target which just means "do nothing and let the URI pass through unchanged":
RewriteEngine on
RewriteCond $1 !^(index\.php)
RewriteRule ^(.*)$ - [L,F]
Or you can try combining the condition with the rule:
RewriteEngine on
RewriteRule !index\.php$ - [L,F]
You can either create an error page. Actually, some control panels have an application that will allow their user to create an SSI-enabled 403 (Forbidden) page with .shtml file extension. In cPanel that app. is entitled with "Error Pages" which were found in the "Advanced" section, and the 403 page will be going to saved in 403.shtml basename. If you didn't found such kind of app., you can manually create an SSI-enabled HTML file, only if your server is configured to allow this. If it's not possible, you can still use another extension.
So, the more correct way is to remap the existed error page, such like this:
RewriteCond %{REQUEST_URI} !^/index\.php
RewriteRule ^(.*) /403.shtml
But anyway, what are you trying to do?

Why is my .htaccess file redirecting to full server path instead of relative path?

I've never had a problem with cakePHP before, but something's odd about this server and is causing the redirects in the .htaccess files to behave oddly.
CakePHP uses mod_rewrite in .htaccess files to redirect requests to its own webroot folder. The problem is that the redirects are listing the wrong path and causing a 404 error. My CakePHP application, which is stored in the listings directory, has a .htaccess file as follows:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^$ app/webroot/ [R=301,L]
RewriteRule (.*) app/webroot/$1 [R=301,L]
</IfModule>
(*note that the R=301 causes an external redirect so we can see what is going on from our end. It should really omit this flag and do the redirect internally, transparent to end-users)
This is supposed to redirect any request from http://hostname.com/~username/listings/ to http://hostname.com/~username/listings/app/webroot/
However, rather than simply adding “app/webroot/” to the end as it is supposed to, it is adding the full server path ( /home/username/public_html/listings/app/webroot/ ) resulting in the final URL http://hostname.com/home/username/public_html/listings/app/webroot/ which is obviously incorrect and triggers a 404 error.
The hosting is on a shared hosting account, so that limits what I can do with the settings. I've never seen this happen before, and I'm thinking it's something wrong from the hosting side of things, but if anyone has some helpful suggestions then I can put them to the hosting company as well.
The solution to your question can be found towards the bottom of this page in the cakephp book:
For many hosting services (GoDaddy, 1and1), your web server is actually being served from a user directory that already uses mod_rewrite. If you are installing CakePHP into a user directory (http://example.com/~username/cakephp/), or any other URL structure that already utilizes mod_rewrite, you'll need to add RewriteBase statements to the .htaccess files CakePHP uses (/.htaccess, /app/.htaccess, /app/webroot/.htaccess).
I've deployed CakePHP from my profile's public_html folder as well. I had to change 3 the same .htaccess files mentioned above. Just add RewriteBase /~username/ to the .htaccess files just after RewriteEngine on!
Try removing .htaccess from main file... It worked for me
It was quite simple (using uolhost shared host):
Edit both .htaccess files:
/webroot/.htaccess
/.htaccess
Add the following line:
RewriteBase /
Here is the whole /webroot/.htaccess file:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]

.htaccess mod_rewrite issue

Almost in any project I work on, some issues with .htaccess occur. I usually just find the easiest solution and leave it because I don't have any knowledge or understanding for Apache, servers etc. But this time I thought I would ask you guys.
This is the files and folders in my (simplified) setup:
/modrewrite-test
.htaccess
/config
/inc
/lib
/public_html
.htaccess
/cms
/navigation
index.php
edit.php
/pages
index.php
edit.php
login.php
page.php
The "config", "inc" and "lib" folders are meant to be "hidden" from the root of the website. I try to accomplish this by making a .htaccess-file in the root that redirects the user to "public_html". The .htacess-file contains this:
RewriteEngine On
RewriteRule (.*) public_html/$1
This works perfect. If I type "http://localhost/modrewrite-test/login.php" in my browser, I end up in public_html/login.php which is my intention. So this works fine. The .htaccess-file in "public_html" contains this:
RewriteEngine On
# Root
RewriteRule ^$ page.php [L]
# Login
RewriteRule ^(admin)|(login)\/?$ login.php [L]
# Page (if not a file/directory)
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ page.php?url=$1 [L]
The first rewrite just redirects me to public_html/page.php if I try to reach "http://localhost/modrewrite-test/". The next rewrite is just for the convenience of users trying to log in - so if they try to reach "http://localhost/modrewrite-test/admin" or "http://localhost/modrewrite-test/login" they will end up at the login.php-file. The third and last rewrite handles the rest of the requests. If I try to reach "http://localhost/modrewrite-test/bla/bla/bla" it will just redirect me to public_html/page.php (with the 'url' GET-variable set) instead of finding a folder called "la", containing a folder named "bla" and etc.
All of these things work perfect but a minor issues occurs when I for instance try to reach "http://localhost/modrewrite-test/cms/navigation" without a slash at the end of the URL. When I try to reach that page the browser is somehow redirected to "http://localhost/modrewrite-test/public_html/cms/navigation/". The correct page is shown but why does it get redirected and add the "public_html" part in the URL? The desired behavior is that the URL stays intact and that the page public_html/cms/navigation/index.php is shown.
The files and folders in the (simplified) can be found at http://highbars.com/modrewrite-test.zip
I ran into the same problem with "strange" redirects when trying to access existing directory without slash at end. In my case this redirection was done by mod_dir Apache module. To disable redirection I used DirectorySlash directive. Try putting in .htaccess files following string:
DirectorySlash Off
RewriteBase may help. Try this in public_html/.htaccess:
RewriteEngine On
RewriteBase /
Add the following to /modrewrite-test/.htaccess:
RewriteBase /modrewrite-test
Just to be on the safe side, I'd add the same rule also to /modrewrite-test/public_html/.htaccess. I found that having RewriteBase always set prevents a lot of potential problems in the future. This however means that you might need to update the values if you change the URI structure of your site.
Update:
I don't think that this is possible with your current folder structure. I believe that the problem is that existing subdirectories prevent rewrite rules from firing. Note the behavior please - everything works fine while you are working with non-existent files and directories, thanks to these two conditions:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
However if you try to open any index file from an existing subdirectory, you get redirected to .../public_html/.... Since you can properly open /modrewrite-test/cms/navigation/edit.php, I can only assume that the request is being overwritten by some Apache core directive, which adds slashes at end of folder URLs. Notice that everything works fine if you have an ending-slash at each URL (i.e. the Apache core directory does not need to "correct" your URL, thus everything gets rewritten by your own rewrite rules).
Suggested solution (unless anyone can advise better):
Change /modrewrite-test/public_html/.htaccess as follows:
RewriteEngine On
RewriteBase /modrewrite-test
# Page (if not a file/directory)
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ page.php?url=$1 [L]
Then Remove all PHP files from subfolders and use the Front Controller pattern, i.e. route all requests through your main page.php file and do not delegate anything down below.
You can then use the Factory pattern to initiate individual UIs (i.e. navigation/edit.php) directly from your main page.php file based on contents of $_GET['url'] (make sure to properly sanitize that).
Update #2:
This other post on StackOverflow advises on project structure used by Zend Framework - it essentially shows the approach which I suggested above. It is a valuable information asset regardless if you use Zend Framework or not.