I have an application that routes all requests through index.php.
Here's my setup:
I access the application at http://www.example.com/sample/
On the filesystem, the application sits in /home/chris/www/sample/
The web-accessible directory of the application lives at /home/chris/www/sample/app/web.
The DocumentRoot is set to /home/chris/www
/home/chris/www/sample/.htaccess is configured as follows:
RewriteEngine on
RewriteCond %{REQUEST_URI} ^/sample/(.+)$
RewriteCond %{DOCUMENT_ROOT}/sample/app/web/%1 -f
RewriteRule ^/sample/(.*)$ %{DOCUMENT_ROOT}/sample/app/web/%1 [L]
RewriteRule ^(.+)$ index.php?ws_page=$1 [L,NC,QSA]
I've tried multiple configurations, but haven't figured out why I keep getting 404's on calls to "real" files.
Sample 404:
`http://www.example.com/sample/_css/960/reset.css`
(which I want to have rewritten to /home/chris/www/sample/app/web/_css/960/reset.css)
EDIT
I have already tried
RewriteCond %{REQUEST_URI} !-f
RewriteCond %{REQUEST_URI} !-d
RewriteCond %{REQUEST_URI} !-l
and they did not work, because the %{REQUEST_URI} prefix does not match the filesystem prefix of these files.
EDIT 2
To clarify, I want requests of the form
`http://www.example.com/sample/foo/bar`
to be rewritten to the filesystem object /home/chris/www/sample/app/web/foo/bar, but only if that filesystem object exists.
One of the biggest bear-pits in reading the mod_rewrite documentation in the difference in behaviour in a system (that this the main and vhost configs that apache reads on start-up and those directive processes in a per-directory context. See the Per-directory Rewrites subsection of the RewriteRule documentation for further details.
When using the rewrite engine in .htaccess files the per-directory prefix (which always is the same for a specific directory) is automatically removed for the RewriteRule pattern matching and automatically added after any relative (not starting with a slash or protocol name) substitution encounters the end of a rule set. See the RewriteBase directive for more information regarding what prefix will be added back to relative substitions.
and later
The removed prefix always ends with a slash, meaning the matching occurs against a string which never has a leading slash. Therefore, a Pattern with ^/ never matches in per-directory context. What you've done is to code around this.
Incidentally, this is why it is always safer to specify a RewriteBase, as the engine gets this wrong without this.
BTW, this second quote can be wrong because the prefix add-back occurs at the then of the rule set execution, and if you have a successful rule which is to a different relative branch (that is the target starts with a /) but without the [L] flag set, then the engine falls through to any subsequent rules with a leading / set. Most confusing, so my general advice is never rely on fall-through rules. Always force an immediate internal or external redirect on a successful substitution in a per-directory context as the engine has this and a couple of other bugs in this fall-through processing.
Have your code like this:
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /sample
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+sample/(.+)\s [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond /home/chris/www/sample/app/web/%1 -f [NC]
RewriteRule ^ /sample/app/web/%1 [L]
# If the request is not for a valid file
RewriteCond %{REQUEST_FILENAME} !-f
# If the request is not for a valid symlink
RewriteCond %{REQUEST_FILENAME} !-l
# If the request is not for a valid directory
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ index.php?page=$1 [L,QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
These two rules will skip files (-f) and directories (-d) which actually exist.
Mad bonus points to whomever can explain to me why my the EOS anchor ($) was to blame for the RewriteRule not working.
I wound up with this:
RewriteEngine on
RewriteCond %{REQUEST_URI} ^/sample/(.+)
RewriteCond %{DOCUMENT_ROOT}/sample/app/web/%1 -f
RewriteRule ^(.*)$ app/web/$1 [L,NC,QSA]
RewriteCond %{REQUEST_URI} !(^/sample/app/web)
RewriteRule ^(.+)$ index.php?ws_page=$1 [L,NC,QSA]
Many thanks to all who helped me diagnose this weirdness.
Related
example.com/wp
or
example.com/wp/
<- This is what homepage link used to be like and I'm trying to keep it this way.
But I want the server to serve some static page from another subfolder as a front page (but to keep all the other wp contents at the same places)
My static page (several of them tbh) are stored in root/subf1/
I was able to redirect to the desired subfolder, but the path also shows up in the URL.
Is it possible to change example.com/subf1 to example/wp?
Here's my current htaccess. Maybe I need to create another one in a static page folder?
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www.)?example.com$
RewriteCond %{REQUEST_URI} !^/subf1/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /test/page/$1
RewriteCond %{HTTP_HOST} ^(www.)?example.com$
RewriteRule ^(/)?$ /subf1/index.html [L]
</IfModule>
RedirectMatch "^/wp$" "https://example.com/subf1/"
Thank you a lot for your time
RedirectMatch does only "external redirections", so you probably want internal redirection with a RewriteRule (without the R flag).
So instead of RedirectMatch try:
RewriteRule ^wp$ https://example.com/subf1/ [L]
PS: Generally it is good to go for redirect/redirectmatch instead of going for mod_rewrite, but if you are already using mod_rewrite directives it will be less confusing to stick to it and not mix direcitves from one or the other.
I currently have this line in my .htaccess file making URLs "pretty" for pages.
RewriteRule ^([A-Za-z0-9-]+)/$ /directory/?type=page&title=$1 [L]
However, I sometimes have sub-pages (/page/sub-page/sub-page/), yet this line only supports one level (/page/).
How can I alter this code to support sub-pages (any amount) and make the title variable something like:
&title=page/sub-page/sub-page
/ being the seperator.
I know that this will definitely be a huge help:
RewriteRule loop in .htaccess not working
However, due to my lack of knowledge with regex and mod-rewrite, I don't know how to make it properly work with what I already have.
Try this:
AllowEncodedSlashes On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^([/a-z0-9-]+)/?$ /directory/?type=page&title=$1 [NC,B,L]
Don't worry about A-Z because of the NC flag.
After doing some regex research, and doing some testing, it seems like this is the answer to my problem:
RewriteRule ^(([a-zA-Z0-9-]+)/(([a-zA-Z0-9-]+)\/?)+)$ /directory/?type=page&title=$1 [L]
I altered my previous code and allowed support for multiple sub-directories. Then I placed it into a capture group and placed that data into the title variable.
I thought I had this figured out but no dice... I'm attempting to rewrite a domain but preserve the subdirectory paths:
www.olddomain.com/sub/directory/page.php
TO
www.newdomain.com/sub/directory/page.php
The following two directives are both needed. The first is the attempt to accomplish the above. The second is inserting a hidden "index.php" before every URL.
RewriteCond %{HTTP_HOST} ^(www\.)?olddomain\.com$
RewriteRule ^(.*)$ http://www.newdomain.com/$1 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
Curently, no matter what URL I visit on olddomain.com, it takes me to newdomain.com/index.php. Maybe it is inserting the "index.php" from the previous site... I inserted [L] to attempt it to stop parsing the .htaccess file but it doesn't like that either. Any direction would be much appreciated.
You need to make sure to remove any rules you have on your old site (if the site resides in a different place than your new domain), otherwise, you need to make sure that the redirect is the very first rule, right under the RewriteEngine On line.
Your rule:
RewriteCond %{HTTP_HOST} ^(www\.)?olddomain\.com$
RewriteRule ^(.*)$ http://www.newdomain.com/$1 [R=301,L]
is correct. And as long as there's nothing before it, it should work.
Make sure you've cleared your browser's cache.
I have a simple website comprised of one page with a div that gets populated with ajax content based on the links the user selects. This site is running on an Apache server with an .htaccess file in the domain's root directory. Requests to www.mydomain.com are directed to scripts/index.php while requests for dynamic content (but not resource files) are directed to the same .php script with the requested content passed as a parameter (e.g., www.mydomain.com/myProject will be rewritten as scripts/index.php?dynContent=myProject).
My rewrite rules are below and for the most part they are performing those described tasks properly; however, I've encountered some URLs that do not match the second condition even though I would expect them to -- though this is the first time I've had to write rules for an .htaccess file so I don't really know what I'm talking about... A good example of a URL that fails the second condition is www.mydomain.com/about, but I've encountered many more just by testing random words/letters.
Can you tell me why www.mydomain.com/about fails the second condition? Also, if there is a more elegant way to achieve the objectives I described above, I would love to learn about it. Thank you!!
RewriteCond %{HTTP_HOST} ^(www.)?mydomain.com$ [NC]
RewriteRule ^(/)?$ scripts/index.php [L]
RewriteCond %{REQUEST_URI} .*[^index.php|.css|.js|.jpg|.html|.swf]$
RewriteRule .* scripts/index.php?dynContent=$1 [L]
This is because regex in your 2nd rules is incorrect.
Change your code to:
RewriteCond %{HTTP_HOST} ^(www\.)?mydomain\.com$ [NC]
RewriteRule ^(/)?$ scripts/index.php [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !\.(php|css|js|jpe?g|html|swf)$
RewriteRule ^(.*)$ scripts/index.php?dynContent=$1 [L]
Hi
I need some help (the solution and the explanation please)
In my application there is a php page called page.php which gets a parameter page by GET and delivers content accordingly.
What I want is:
Make this page the entry point, catch all and redirect it to page.php.
Use the URI as the page parameter value. (domain.com/string will become domain.com/page.php?page=string)
When I used ^(.*)$ page.php?page=$! it was working, except it also manipulated every resource that was called (js, css, images, etc..)
Thanks
You need to add RewriteCond statements to avoid any existing files.
RewriteEngine on
RewriteBase /
# Allow files that exists to bypass rewrites
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ page.php?page=$1 [L,QSA]