.htaccess: redirect if file doesn't exists - .htaccess

It is quite popular question, but there is some distinction in my case that makes all more difficult.
Apache2 web server, Yii2 framework with prettyUrl turned on.
Here is initial .htaccess file, provided by Yii2:
RewriteEngine on
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# otherwise forward it to index.php
RewriteRule . index.php
There is /docs web directory. And I would like to get files from it if they are exist and redirect to /docs-generator/create?file=<file_name> if the file doesn't exists.
So, I have added a rule:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} ^/docs
RewriteRule ^docs/([\w-_.]+) http://kz_proj.test/docs-generator/create?file=$1 [L]
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# otherwise forward it to index.php
RewriteRule . index.php
It's works but quite strange... First of all, I can't remove my test hostname from http://kz_proj.test/docs-generator/create?file=$1. It doesn't work without full name. The second one is about ^/docs and ^docs/([\w-_.]+) without the leading character. Why first part of these rules can't be the same in my case?
I guess something wrong with the rules...

You can use:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^docs/([\w-_.]+) /docs-generator/create?file=$1 [L,R=301]
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# otherwise forward it to index.php
RewriteRule ^ index.php
It works with the domain name because it is necessarily a redirect in this case, but not without. I added [R=301] to force the redirection.
No need to add RewriteCond %{REQUEST_URI} ^/docs
because the test is the same with RewriteRule ^docs
And why first part of these rules can't be the same in your case ?
REQUEST_URI always start with a /
and RewriteRule test path never start with a / in .htaccess (why????)

Related

Redirecting all requests from a subdirectory to a specific file

I wanted to redirect all requests from a specific subdirectory (/portfolio/*) to a specific file in the root of my website (portfolio.php). This way I want to be able to create project-specific pages within the same file as where the overview is being created.
I tried the following, but it didn't work since it stopped images from loading (images were located in the /images/portfolio/* directory), and it also disables my custom ErrorDocument...
RewriteRule /portfolio/(.*) /$1 [PT]
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /portfolio.php [L]
Anyone has an idea on how to fix this?
Try getting rid of the first rule and adding the pattern to your last rule:
RewriteRule ^portfolio.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^portfolio/(.+)$ /portfolio.php [L]
And for good measure, make sure multiviews is turned off:
Options -Multiviews

Redirect file type specific requests

In my app, I have the srcs of many images like this:
path/other-path/my-image.jpg
This can get long and can expose some of my file structure to the outside world.
What can I do in .htaccess to redirect a given file extension to a directory?
i.e. my image src is simply "my-image.jpg", .htaccess sees that is a .jpg file and redirects to the folder "www.site.com/my-jpgs/" were "my-image.jpg" resides, thus loading the image.
Here is what I have at the moment:
Options +FollowSymLinks
IndexIgnore */*
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/importers
RewriteCond %{REQUEST_URI} !\.(gif|jpg|png)$
RewriteRule ^(.*)$ public_html/index.php
RewriteBase /
# Ignore rule if the real path exists, use that instead.
RewriteCond %{REQUEST_FILENAME} !-f
# Only use the filename and extension.
RewriteRule (.[^/]*)\.(gif|jpg|png) public_html/images$1.$2 [R,L]
I've sort of got it working, except the browser makes two requests that look like this:
Request URL:http://www.view.com/activity/enquiry/dropdown-btn.gif
Request URL:http://www.view.com/public_html/images/dropdown-btn.gif
The second being correct, how do I correct this so it doesn't make the first incorrect request?
Ordering of rewrite rules is very important in .htaccess. Your problem is incorrect ordering of your rule. You need to move last rule to the top just belowRewriteEngine Online to have external redirect before sending everything off toindex.php`:
Options +FollowSymLinks
IndexIgnore */*
RewriteEngine On
RewriteBase /
# Ignore rule if the real path exists, use that instead.
RewriteCond %{REQUEST_FILENAME} !-f
# Only use the filename and extension.
RewriteRule ^(?:[^/]+/)*([^.]+\.(?:gif|jpe?g|png))$ images/$1 [R,L,NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/importers
RewriteCond %{REQUEST_URI} !\.(gif|jpe?g|png)$
RewriteRule ^ index.php [L]

Yii switching to HTTPS

I know, that switching to HTTPS has nothing to do with Yii, and it is mainly adding
rewrite rules in .htaccess.
Now I am facing some problems. After I changed my .htaccess file
from
RewriteEngine on
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# manual change the url base
RewriteBase /
# otherwise forward it to index.php
RewriteRule . index.php
to
RewriteEngine on
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://my.domain.de/$1 [R,L]
# manual change the url base
RewriteBase /
# otherwise forward it to index.php
RewriteRule . index.php
The first login page is automatically redirected from http to https as I wanted, but there are no css and images loaded. I have noticed that all the paths to these files are relative, so https://my.domain.de/css/print.css is not found, but http://my.domain.de/css/print.css is accessible. And if I go through the links in web-site css and images are everywhere missed.
Any suggestions?
Rewrite conditions only affect the immediately following rule. The two !-f and !-d conditions need to be applied to the routing rule: RewriteRule . index.php. Otherwise, everything blindly gets routed to index.php and request for files that actually exist won't get fulfilled.
Additionally, the redirect needs to be before the routing rule, so you need to move your conditions to be right above your routing rule:
RewriteEngine on
# manual change the url base
RewriteBase /
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://my.domain.de/$1 [R,L]
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# otherwise forward it to index.php
RewriteRule . index.php

Configure htaccess to load static pages

Im working on a server with the following htaccess:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule .* index.php
RewriteRule ^[^/]*\.html$ index.php
RewriteRule ^/(typo3|typo3temp|typo3conf|t3lib|tslib|fileadmin|uploads|showpic\.php)/ - [L]
RewriteRule ^/(typo3|typo3temp|typo3conf|t3lib|tslib|fileadmin|uploads|showpic\.php)/.*$ - [L]
Now they asked me to prepare a static page inside their server, lets call it http://www.myserver.com/mystaticpage.html
The problem is that when i try to access that url, it redirects to index.php. How could I alter the htacces file to address this problem without messing anything with the installed CMS?
Try this:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond ${REQUEST_URI} !^/(typo3|typo3temp|typo3conf|t3lib|tslib|fileadmin|uploads|showpic\.php)
RewriteRule .* index.php
The rules you used before were redundant: if .* is rewritten to index.php then why also rewrite ^[^/]*\.html$ index.php to it? it already matched previous rule...
They also overlapped - since the three RewriteCond conditions were only applied on the first rule. So the second rule was also applied to static files on disk.
Also, the two rules that were listed last had no effect whatsoever. Either you needed to list them first, or not at all. I converted them to an additional RewriteCond since they were only attempted to avoid rewrite on certain uris

htaccess redirect problems

My .htaccess looks like this:
RewriteEngine on
RewriteCond %{REQUEST_URI} !(\.gif)|(\.jpg)|(\.png)|(\.css)|(\.js)|(\.php)|(\.swf)|(\.xpi)|(\.ico)|(\.src)$
RewriteCond %{REQUEST_URI} ^(.*)$
#RewriteCond %{REQUEST_FILENAME} ! -f
RewriteRule (.*)$ view.php?picid=$1 [L]
Problem is that when I visit www.example.com, it’s sending me to view.php. There is an index.php file in my root directory. How do I get .htaccess to ignore the index file?
Try this rule:
RewriteCond %{REQUEST_URI} !.*\.(gif|jpg|png|css|js|php|swf|xpi|ico|src)$ [OR]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.+) view.php?picid=$1 [L]
The important changes I made:
The regular expression in your first RewriteCond is faulty. The $ anchor is only applied to the last option in the alteration.
The second RewriteCond directive is useless.
The third RewriteCond that’s commented out will do just what you want: Check if the requested URI path can be mapped to an existing file.
Altered the quantifier from zero or more to one or more characters. That will exclude the empty URI path when / is requested.
Remove the # from the fourth line and remove the space between the exclamation mark (!) and the -f
RewriteCond %{REQUEST_FILENAME} !-f
This line says that if the file doesn't already exist on the server, in this case, index.php, then continue and do the rewrite that follows.
Also check you've got both a DirectoryIndex as well as checking against any valid directories.
DirectoryIndex index.php
RewriteCond %{REQUEST_FILENAME} !-d
Which would leave you with this cleaner version:
DirectoryIndex index.php
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*)$ view.php?picid=$1 [L]
This first sets up index.php as the default file. Then you run the Rewrite engine, and if the requested file does not already exist on the server as either a file or a directory, will pass things on to the view.php file and run its magic.

Resources