.htaccess mod_rewrite subdirectory to URL parameter - apache

I hope this was not asked over and over again before, but I didn't get further to an answer using google, w3schools and so on. So here is my question:
I'm writing a script that creates kind of an index of projects that I have on my homepage and makes a nice list with images and teaser text based on an info file. I mostly have my projects on github and the readme is in markdown so I thought I could dynamically generate the HTML from the markdown of the latest blob from github on demand using PHP so it gets updated automatically.
My directory structure looks like this:
projects
project1
.remoteindex
.info
project2
.remoteindex
.info
index.php
.htaccess
So when just domain.tld/projects/ is requested I get the info from .info and make a nice index of all projects. But if domain.tld/projects/project1/ is request it, I want to internally redirect it to domain.tld/projects/?dir=project1 to do my markdown parsing and so on. But domain.tld/projects/project1/image.png should not be redirected.
This is what I tried:
.htaccess
RewriteEngine on
RewriteRule ^([^/]+)/?$ index.php?dir=$1 [R,L]
I made it redirect instead of rewrite so that I can see what the error is because I just got an 404. The URL that I get redirected to is domain.tld/home/www/web310/html/projects/index.php?dir=project1 so obviously there is something going wrong with the internal structure of the web server an paths an whatever.
I hope you can understand my problem an I would be very pleased if someone could help me, because I'm totally lost on .htaccess anyway.
Edit:
See my answer below for the used .htaccess.
The strange thing is that if I have an index.html in on of the subdirectories, my local web server (Apache with XAMPP for Mac OS X 1.7.3) does not rewrite and the index.html gets displayed, without one it works correctly.But on my real web server that serves my homepage it rewrites both with and without index.html (which is what I want). Any hints on that?

Thanks for all the help so far! You guys are just awesome!
I figured out that a symbiosis of both of your solutions works well for me:
RewriteEngine on
RewriteBase /projects
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} -d
RewriteRule ^([^/]+)/?$ index.php?dir=$1 [QSA,L]
Of course only without [R], this was my fault. (See my question edit for another question please).

You need to add a RewriteBase /projects to the htaccess.
That way the redirect will work properly.
Edit:
RewriteEngine on
RewriteRule ^index.php - [L]
RewriteRule ^([^/]+)/?$ index.php?dir=$1 [R,L]

Following what you ask, this is important not to do a redirect, but let the rewriterule modify internally the URL i.e. the RewriteRule should not end with [R,L] but rather [L] and maybe the "query string append" directive to keep what's after the ? so this should probably be [QSA,L].
Now here's how I'd do to avoid rewriting static files: if it's not a file then (and only then) test it:
# if it's not a file...
RewriteCond %{SCRIPT_FILENAME} !-f
# ... and it's a dir
RewriteCond %{SCRIPT_FILENAME} -d
# ... then rewrite it internally and stop further processing:
RewriteRule projects/([^/]+)(/?)$ index.php?dir=$1 [QSA,L]
And now two hints:
Please try to use the RewriteLog directive: it helps you to track down such problems:
# Trace:
# (!) file gets big quickly, remove in prod environments:
RewriteLog "/web/logs/mywebsite.rewrite.log"
RewriteLogLevel 9
RewriteEngine On
My favorite tool to check for regexp:
http://www.quanetic.com/Regex (don't forget to choose ereg(POSIX) instead of preg(PCRE)!)

Related

htaccess doesn't load new js/css from another vhost

Ok, so here it is!
I have two virtual hosts, named main.aaa.com and static.aaa.com.
I have a htaccess rule in main.aaa.com that for each path that contains js|css|img|ico will load them from static.aaa.com.
This is the htaccess for main.aaa.com:
Options +Indexes
Options -MultiViews
Options +FollowSymLinks
# Turn on the RewriteEngine
RewriteBase /
RewriteEngine On
#
# Rules
#
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule !\.(css|js|ico|img)$ index.html [PT,L]
RewriteRule ^(.+\.(css|js|img|ico))$ http://static.aaa.com/$1 [L]
What's going on is that everything works perfectly, absolutely perfect, but...
if I create a new file in static/js folder and try to load it in main.aaa.com index file, it just gives a 200 OK, file not changed, and by looking into it it seems that htaccess doesn't even bother to look for the file in static vhost.
I have changed file permissions to 755, all of the files have the same permissions and the same owner, only that the new ones that I create are not loaded.
Any help would be much appreciated! Thank you!
[EDIT]: I tried also to rename a file that is now correctly loaded, because I thought I am missing something about file permissions. Stopped working. Renamed it back to previous name and it loads. So, I am thinking, is there a history of files or something that I can clear? I am at the point to break something, anything!
Using ubuntu 14.04 LTS and apache 2.4 if that helps.
I have found a solution to my problem, I don't really understand why it works, I just hope it does not introduce any other problems when I push my files to my hosting.
So here it is, if anybody is as stupid as me :), I have changed and moved this line:
RewriteRule ^(.+\.(css|js|img|ico))$ http://static.aaa.com/$1 [L]
above this line
RewriteRule !\.(css|js|ico|img)$ index.html [PT,L]
the final result being this one:
RewriteRule ^(.+\.(css|js|img|ico))$ http://static.aaa.com/$1 [R,L]
RewriteRule !\.(css|js|ico|img)$ index.html [PT,L]
Good luck!
EDIT: maybe the answer is that redirects, with R flag, must be written first. Maybe.

Invisibly rewriting root to subdirectory using mod_rewrite (ajaxplorer)

I've been looking on various sites reading mod_rewrite examples for a few hours, and have used it many times before successfully... but I'm trying something new with it now and can't for the life of me get it working!
I'm using a PHP file manager tool called AjaXplorer, I have it in a subdirectory on the root of my server /ajaxplorer-core-4.0.4. When I go to the root of my site http://domain.com/ I want it to invisibly redirect to the /ajaxplorer-core-4.0.4 folder (but still show the root domain in the address bar).
I still want to be able to access the other files/directories on the root as normal just typing in the path.
I assume this is possible? Seems relatively simple but I just can't get it working.
AjaXplorer seems to load js files and images etc from /ajaxplorer-core-4.0.4/plugins, I have a feeling that's where it's tripping me up.
Any pointers would be massively appreciated! Thanks
Found it on another answer luckily :)
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www.)?site.com$
RewriteCond %{REQUEST_URI} !^/subdir/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /subdir/$1
RewriteCond %{HTTP_HOST} ^(www.)?site.com$
RewriteRule ^(/)?$ subdir/index.php [L]
Here's the wiki of serverfault.com
The howto's htaccess official guide
The official mod_rewrite guide
And if that's not enough:
Two hints:
If you're not in a hosted environment (= if it's your own server and you can modify the virtual hosts, not only the .htaccess files), try to use the RewriteLog directive: it helps you to track down such problems:
# Trace:
# (!) file gets big quickly, remove in prod environments:
RewriteLog "/web/logs/mywebsite.rewrite.log"
RewriteLogLevel 9
RewriteEngine On
My favorite tool to check for regexp:
http://www.quanetic.com/Regex (don't forget to choose ereg(POSIX) instead of preg(PCRE)!)

Mod_rewrite rules from root

This problem has been bugging me for a while now.
I have a created a small site engine and I'm using mod_rewrite to tell the engine what page to proccess, SEO friendly links is a bonus :).
This is how it's works today:
the adress http://www.example.com/site/page
becomes http://www.example.com/engine.php?address=page
But what i want is:
the adress http://www.example.com/page
becomes http://www.example.com/engine.php?address=page
Everything works fine if i create a psuedo directory for the calls (/site) but when i try to do the same from the root strange things start to happends.
RewriteBase /
RewriteRule ^site/(.*) engine.php?%{QUERY_STRING}&address=$1
Works fine: /site/about/contacts becomes eninge.php?address=about/contacts
RewriteBase /
RewriteRule ^(.*)$ eninge.php?%{QUERY_STRING}&address=$1
Doesn't work, for some reason /about/contacts becomes eninge.php?address=eninge.php
(.*) means catch anything. Have you tried exluding files and directory before your catch-all ? Because it will cause an infinite recursion without it.
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ eninge.php?%{QUERY_STRING}&address=$1 [L]
More information is available in the official documentation: http://httpd.apache.org/docs/current/mod/mod_rewrite.html
Update: You should also specify [L] at the end of your rule, to tell Apache to end the rewriting process here.
Check the RewriteLog (this has been updated in 2.4, check current docs if not using 2.2):
RewriteLog "/usr/local/var/apache/logs/rewrite.log"
RewriteLogLevel 3
This will show you exactly what mod_rewrite is doing and allow you to tune your configuration based on its output. Beware - it grows very quickly, and should never be used in production environments.
As an aside, you have some typos in your post - worth verifying that these differ from your config.
RewriteCond %{REQUEST_FILENAME} !^engine.php
RewriteRule (.*) engine.php?address=$1 [QSA,L]
Try this. What you have is causing the rewrite to loop around and first do engine.php?address=about/contacts as you were expecting, but then go around again and rewrite that to engine.php?address=engine.php. Make sense? The [QSA,L] is a Query String Append and Last flag that will add the query string to your URL and tell the rewrite engine to stop looking for rewrites. The RewriteCond %{REQUEST_FILENAME} !^engine.php is to check that you haven't already specified the engine rewrite by ensuring the current URL doesn't start with engine.php. This is necessary if you are writing this in an .htaccess file rather than the .httpd config files.

Mod Rewrite Hide Folder

I think this is a pretty simple question.
How do you an apache rewrite to hide a folder.
EX: www.website.com/pages/login.php to www.website.com/login.php
or www.website.com/pages/home.php to www.website.com/home.php
The folder needs to alway be hidden. thanks
I assume what you want is for the browser to request /home.php but the server to actually use the file located at /pages/home.php, right? If so, this should work:
Make sure the apache mod_rewrite module is installed. Then, use something like this in your apache config, virtual host config, or (less desirable) .htaccess file:
RewriteEngine On
RewriteRule ^/(.*)$ /pages/$1
The rules use regular expressions, so you may want to look at a reference on that topic if you're unsure. Read the manual for more info on other directives (RewriteCond can be very useful) or rule options.
I know the original post here was from a couple years ago, but it's been coming up first in the search engine, so maybe this will help others looking to hide a folder name in the URL.
Not exactly what original poster wanted, but along the same lines.
RewriteCond %{HTTP_HOST} ^mydomainname\.com$ [OR]
RewriteCond %{HTTP_HOST} ^www\.mydomainname\.com$
RewriteCond %{REQUEST_URI} !^/subfoldername/
RewriteRule (.*) /subfoldername/$1
The above example would redirect any request to mydomainname.com or www.mydomainname.com to the subfoldername directory in the root directory for the domain, and the subfolder name would not appear in the URL.
If your example actually reflects the files you need, then in your .htaccess file:
#Options +FollowSymLinks
RewriteEngine On
RewriteRule ^/pages/(.+)\.php $1\.php [NC, L]
Also, if the directory has read permission, it cannot be, in reality "hidden". I assume you mean that it no longer appears in the url.

.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.