Why is the RewriteBase not working? - apache

Here is what I am trying to do:
domain is thinkingmonkey.me
domain has 127.0.0.1 as IP addr
mod_alias is installed.
I have a conf file called directories.conf. In which I have all the configuration pertaining to directories. directories.conf is included in httpd.conf
My directories.conf has
Alias /runs /xhprof/xhprof_html
<Directory /mysite/xhprof/xhprof_html>
Order allow,deny
Allow from all
AllowOverride All
</Directory>
In /mysite/xhprof/xhprof_html/.htaccess. I have the following:
RewriteEngine on
RewriteBase /runs
RewriteRule .* index.php
All I am trying to do is to direct any request under /mysite/xhprof/xhprof_html/ to index.php.
When I request for thinkingmonkey.me/runs with no trailing slashes I get 404 not found.
So, I infer that RewriteBase is not working.
What am I doing wrong?

Alias requires a tailing slash. Nothing to do with RewriteBase.
You could use a rewrite rule to add the slash when needed though. Something like:
RewriteRule ^run$ /run/ [R=301,L]
Put this rule in the htaccess in the root of your server (not in /xhprof/xhprof_html)

Related

Split DocumentRoot using Apache Alias per request path

I'm trying to slowly take over an existing website, route per route. I found Apache's Alias(Match) which seems to allow me to set a different (content) document root per request. But I'm failing with trailing slashes and more complex paths.
My goal now is to have the old website serve everything as it is used to. And to have a new website, serving a first specific request, say /foo and /foo/*.
I have my vhost setup like this:
<VirtualHost *:80>
ServerName example.com
UseCanonicalName on
AliasMatch ^/foo/(.*)$ /www/new/$1
AliasMatch ^/foo$ /www/new/$1
<Directory /www/new/>
Options +FollowSymLinks -MultiViews
AllowOverride All
Require all granted
</Directory>
DocumentRoot /www/old
<Directory /www/old/>
Options +FollowSymLinks -MultiViews
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
In both directories I have an .htaccess with:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.*)$ index.php/$1 [L]
The index.php's show 'old' or 'new' depending on their directory.
What happens to the different routes I test:
When requesting example.com/bar it shows 'old'.
When requesting example.com/foo it redirects too /foo/, and then shows 'new'.
When requesting example.com/foo/bar it shows 'old'.
I don't want the forced redirect of /foo to /foo/. And I want /foo/bar to show 'new'.
I've been following Apache's mod_alias to get the multiple AliasMatch directives to catch anything after /foo but apparently that's not working correctly. Also, I don't read anything there of the trailing slash being added magically.
Anyone knows the magic tricks?
I've been able to fix this by adjusting the Alias to point to the index.php directly:
AliasMatch ^/foo/(.*)$ /www/new/index.php
AliasMatch ^/foo$ /www/new/index.php
Then /bar and anything else goes to the old website, and /foo, /foo/ and /foo/bar goes to the new website.
There's two downsides to this method:
The .htaccess in the new website is skipped completely. But as I mainly use that for letting the index.php pick up every route, that's fine for now.
Frontend resources like css/js go to the old website. Fix that with another simple alias: example.com/frontend/app.css + Alias /frontend /www/new/public_html/frontend.

AllowOverride and RewriteCond/RewriteRule interactions

I'm trying to set up a site running on Apache 2.4.16 to redirect all www URLs to non-www URLs. I'm using HTML5 Boilerplate's Apache configs to do this (as well as everything else they provide).
https://github.com/h5bp/server-configs-apache/blob/master/dist/.htaccess
This happens on line 380, seen below:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ %{ENV:PROTO}://%1%{REQUEST_URI} [R=301,L]
</IfModule>
I'm using Include to add the whole file to my vhost config for the site, as well as an AllowOverride All for another .htaccess file at my doc root (same one that comes with Laravel 5):
production.vhost.conf (relevant part)
<Directory /var/www/hostname/production>
AllowOverride All
# Include H5BP server configs
Include server-configs-apache/dist/.htaccess
</Directory>
.htaccess (at doc root)
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
RewriteEngine On
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
Now, almost everything from H5BP's .htaccess was working, except for the redirect from www to non-www. After poking around I noticed that the redirect was only working when I'd remove AllowOverride All from the <Directory> block in the vhost. So the doc root .htaccess was somehow overriding the rewrite conditions.
I've actually already fixed my initial issue by moving the doc root .htaccess contents into the vhost file and removing the AllowOverride, but I'm more curious as to why this was happening; more specifically how AllowOverride interacts with RewriteCond and RewriteRule.
My hunch is that the .htaccess in my doc root was overriding the www to non-www redirect, but I'm not sure why that one specifically. For example, the http -> https redirect worked without issue (line 352 of H5BP, uncommented out in mine), it seemed to be just that one redirect. I didnt even think that those rules could be overridden since RewriteCond/RewriteRules feel unique to me.
If there are any, what are the rules that determine how an .htaccess can override a rewrite rule?
If there are any, what are the rules that determine how an .htaccess
can override a rewrite rule?
Conditions and rules don't dictate how .htaccess works. AllowOverride is what allows .htaccess usage. If you have AllowOverride All then .htaccess is allowed, if you have AllowOverride None, then it's not and it will be ignored. In 2.4 None is the default.
.htaccess is per directory so it will take precedence if it's located in a directory that has rules applied as long as .htaccess file usage is allowed there. Which is confgiured in the server config in VirtualHost or Directory directives.
Also using an include for .htaccess in a vhost is a very bad configuration. If you have access to the vhost file or the config, you should create another config and include it with the .htaccess contents.
You should not be using .htaccess files at all actually with access to the server config. See this apache recommendation on not using .htaccess.
https://httpd.apache.org/docs/2.4/howto/htaccess.html#when

mod_rewrite (Apache 2.4) RewriteBase outside htdocs

I stuck on a problem trying to get a my rewrite rules working.
Assume the following setup:
Folder structure like this:
app/
web/ <--- Document-Root
.htaccess <--- My mod_rewrite rules
index.php
vendor/
company/
package/
Folder/
Route.php
The vhost points to "web/" as Document-Root and the security is reduced
so all overrides are allowed:
<Directory "~PATH~\web">
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Order deny,allow
allow from all
Require all granted
</Directory>
Now i try to rewrite simply every request (*) to "Route.php" (internal! no 301 or something).
For my understanding if if would call "www.example.com/a/b" then i would expect that the
request is internal redirected to ~PATH~/vendor/vendor/company/package/Folder/Route.php
where i can fetch everything and take the request in PHP for further processing.
But the rewrite fails. Maybe its not possible to traverse a directory up "/../" ?!
Content of .htacces:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /../vendor/company/package/Folder
RewriteRule .* - [E=ROUTER:Route.php]
# route calls to router /x/y/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . %{env:ROUTER}?mode=htaccess [QSA,L]
</IfModule>
Any help appreciated :)
Thanks in advance!
Try this
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule .* ../vendor/company/package/Folder/Router.php [L]
</IfModule>
EDIT:
I've tried it on my local machine.
This Setup works:
RewriteRule .* vendor/company/package/Folder/Router.php [L]
Seems like its not allowed to forward the Request to directories higher than the Docroot.
I've found this post:
htaccess RewriteRule redirecting to parent directory?
The important Part:
You can't rewrite to outside the document-root. This is a security thing.
EDIT2:
More Information: mod_rewrite - Apache HTTP Server Version 2.4
Quote:
URL-path
A DocumentRoot-relative path to the resource to be served. Note that mod_rewrite tries to guess whether you have specified a file-system path or a URL-path by checking to see if the first segment of the path exists at the root of the file-system. For example, if you specify a Substitution string of /www/file.html, then this will be treated as a URL-path unless a directory named www exists at the root or your file-system (or, in the case of using rewrites in a .htaccess file, relative to your document root), in which case it will be treated as a file-system path. If you wish other URL-mapping directives (such as Alias) to be applied to the resulting URL-path, use the [PT] flag as described below.

Why is Apache Permanent Redirect removing the slash between the domain and the path?

I'm using Apache 2.4, and I set up two virtual directories. One requires SSL, and the other one redirects to it.
If a user attempts to visit https://www.derp.com/derp without /derp existing, they correctly get a 404. But when a user visits http://www.derp.com/derp, Apache incorrectly redirects the user to https://www.derp.comderp, removing the slash between the path and the domain name.
I have no idea what would be causing this.
The following is the setup of my Virtual Host.
<VirtualHost *:443>
ServerAdmin derp#derp.com
ServerName www.derp.com
ServerAlias derp.com
DocumentRoot "C:\Users\derp\Documents\Web Projects\derp"
SSLEngine on
SSLCertificateFile "C:\Apache24\certs\cert.cer"
SSLCertificateKeyFile "C:\Apache24\certs\key.key"
</VirtualHost>
<VirtualHost *:80>
ServerAdmin derp#derp.com
ServerName www.derp.com
ServerAlias derp.com
Redirect permanent / https://www.derp.com/
</VirtualHost>
<Directory "C:\Users\derp\Documents\Web Projects\derp">
Options Indexes FollowSymLinks Includes ExecCGI
AllowOverride All
Require all granted
SSLRequireSSL
</Directory>
Why would Apache be behaving this way?
Bonus Question: Should redirects be handled in my virtual host definition, or should it be handled in the .htaccess file in the web site's physical directory?
Edit:
I'm starting a Laravel project, and by default the public folder does contain a .htaccess file, so here's that guy:
<IfModule mod_rewrite.c>
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
Edit Two:
I tried:
adding a slash at the end of the DirectoryRoot path
replacing the backslashes with forward slashes in the DirectoryRoot path
replacing the backslashes with double backslashes in the DirectoryRoot path
I also removed the .htaccess file from the directory completely.
It redirects correctly when you go from http://www.derp.com to https://www.derp.com. It's just when you specify a path and attempt https that it removes the slash between the domain and the path.
Edit Three:
I also attempted the following suggestion:
Redirect permanent / https://www.derp.com/
Try
RedirectMatch permanent /(.*) https://www.derp.com/$1
or
RedirectMatch permanent (.*) https://www.derp.com/$1
... and instead of redirecting to https://www.derp.comderp, it instead does not redirect, attempts and gives a 404 for http://www.derp.com/derp, but using Apache's 404, instead of throwing a Not Found Exception, as Laravel does without configuration.
Edit Four:
I have also tried:
<IfModule mod_rewrite.c>
Options -MultiViews
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
In the .htaccess file and the behavior did not change at all.
I got it.
The issue did not lay with the rewriting at all, it was the SSLRequireSSL directive under my Directory definition that was causing the problem.
I simply removed this directive, refreshed the cache in all of my browsers, and the site then continued to work correctly. This was discovered through the process of elimination.
The documentation notes:
This directive forbids access unless HTTP over SSL (i.e. HTTPS) is enabled for the current connection. This is very handy inside the SSL-enabled virtual host or directories for defending against configuration errors that expose stuff that should be protected. When this directive is present all requests are denied which are not using SSL.
The emphasis is my own. SSLRequireSSL may have Apache only return a 403 or 404 if HTTP over SSL is not enabled, interfering with the Redirect rule. A rewrite rule such as the one in this answer on Server Fault may be a better alternative depending on your use case:
RewriteEngine On
RewriteCond %{SERVER_PORT} !443
RewriteRule ^(/(.*))?$ https://%{HTTP_HOST}/$1 [R=301,L]
My issue was related to browser caching.
I tried it in a different browser and it worked and then tried again in a private session in the first browser and it also worked.

Troubles with apache - 403 while trying to protect everything but index.php

What I want:
Protecting all files/folders but the index.php.
Apache:
Apache/2.4.2 (Win32) OpenSSL/1.0.1c PHP/5.4.4
Running as Service (xampp 1.8)
Not modified
My project structure
URL: "http://localhost/MyProject/"
PROJECT_DIRECTORY C:/xampp/htdocs/MyProject/
The project directory looks like:
config (folder)
ressources (folder)
sources (folder)
index.php
Problem:
I am having troubles with my .htaccess file as I do always receive a 403 or even a 500 Error.
I tried different settings to achieve the goal but none of these worked. I tried Directory, DirectoryMatch, Files, FilesMatch etc.
But I think it should be as easy as:
# Activate rewrite engine
RewriteEngine on
RewriteBase /
# Redirect all requests to index.php
RewriteRule ^(.*)$ index\.php?/$1 [QSA]
# Deny from all
Order deny,allow
Deny from all
# Allow only index.php
<Files "index.php">
Allow from all
</Files>
Or something like this:
...
# Deny from all
<Directory />
Order deny,allow
Deny from all
</Directory>
# Allow only root dir
<Directory "/MyProject" />
Allow from all
</Directory>
May someone can help me with this?
EDIT: I recently found out, that I cannot use the tag as the .htaccess is valid for the directory I put it in, so there is no need to define that directory inside .htaccess. This did not solve my problem but I know that the second example is wrong.
You can try this:
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/(index\.php)$
RewriteRule ^ - [L,F]
This will let requests for / and /index.php pass through while responding with a 403 Forbidden for anything else.
However, you've got this rule already:
# Redirect all requests to index.php
RewriteRule ^(.*)$ index\.php?/$1 [QSA]
So you don't really need to deny anything if everything is already being routed through index.php