apache mod_rewrite user URLs to index.php - apache

I've always had a fairly standard apache configuration. Right now we're introducing a new concept, user session specific URLs that's going to change things. Basically we have a DocumentRoot and anything such as:
http://example.com/ would hit index.html in the DocumentRoot directive.
But now I'd like to be able to do something like
http://example.com/uid/5/
http://example.com/uid/2
Those should still hit index.html in the DocumentRoot that has been set. The URL is mostly for server-side and client-side scripts to be able to carry out their own tasks.
What's the best way to handle this in Apache? Is mod_rewrite even necessary here?
I also need to be able to support existing paths such as say the following:
http://example.com/foo/bar/something.php will be rewritten to http://example.com/uid/3/foo/bar/something.php but will still hit the same place on the filesystem as before.

You could use mod_rewrite by putting this code in your htaccess
RewriteEngine On
RewriteRule ^uid/([1-9][0-9]*)/(.+)$ /$2?uid=$1 [L]
Example:
http://example.com/foo/bar/something.php -> unchanged
http://example.com/uid/3/foo/bar/something.php -> rewritten to /foo/bar/something.php?uid=3
EDIT: without uid appended
RewriteEngine On
RewriteRule ^uid/[1-9][0-9]*/(.+)$ /$1 [L]

Related

Apache dynamic wildcard host rewrite with dynamic subdomains

I'm currently in the process of converting an old apache vhost, where one is currently created for each new release, to a dynamic host that can handle all the subdomains so we don't have to create a new one all the time. I need some help! We're using apache v2.2.
The Goal
Dynamic all the things. To have a single virtual host that handles all redirects for a specific set of subdomains. The url is below, note that sub1 and branch are dynamic and could be anything.
sub1.branch.sandbox.domain.com
The directory structure for this is as follows:
/var/www/vhosts/branch/sub1.branch.sandbox.domain.com
As you can see above, the directory structure has the branch as a sub-directory before the full url is the name of another sub-directory.
Also, /images/ in the url needs to forward to shared-httpdocs/images for each domain.
The vhost I have so far
<VirtualHost *:80>
ServerName branch.sandbox.domain.com
ServerAlias *.branch.sandbox.domain.com
VirtualDocumentRoot /var/www/vhosts/branch/%0
Options Indexes FollowSymLinks
# Rewrite Engine Stuff Here
RewriteEngine On
DirectoryIndex index.php
# Assets needs to be forwarded - currently not working
RewriteCond %{REQUEST_URI} ^/(css|js|images)/.*
RewriteRule .*$ /var/www/vhosts/%0/shared-httpdocs/%1$ [L]
# The HTTP dispatcher - currently not working
RewriteCond %{HTTP_HOST} ^(.*)\.branch\.sandbox\.domain\.com [NC]
RewriteRule ^(.*)$ /var/www/vhosts/%1/applications/portal/dispatchers/http.php [L,QSA,NS,NE,NC]
</VirtualHost>
The old host I'm trying to copy
This is the old vhost I'm trying to convert from. It's horrible, messy, and our ops has to create a new DNS entry every time. What a joke! I need to sort this out...
<VirtualHost *:80>
# Notice how the stupid convention below will require a new DNS entry each time?
ServerName sandbox.branch.domain.com
ServerAlias sandbox.api.branch.domain.com
DocumentRoot /var/www/vhosts/sandbox.branch.domain.com/applications/portal/httpdocs
<Directory "/var/www/vhosts/sandbox.branch.domain.com/applications/portal/httpdocs">
allow from all
order allow,deny
# Enables .htaccess files for this site
#AllowOverride All
RewriteEngine On
# Rewrite all non-static requests to go through the webapp
RewriteCond %{REQUEST_URI} ^/(css|js|images)/.*
RewriteRule .* - [L]
# Rewrite everything else to go through the webapp
RewriteRule ^(.*)$ /dispatchers/http.php [QSA,L]
</Directory>
<Directory "/var/www/vhosts/sandbox.branch.domain.com/applications/portal/dispatchers">
allow from all
</Directory>
# Allow us to rewrite to the webapp without it being in the webroot
Alias /dispatchers /var/www/vhosts/sandbox.branch.domain.com/applications/portal/dispatchers
# Get shared/ to point to the shared static resources
Alias /shared /var/www/vhosts/sandbox.branch.domain.com/shared-httpdocs
</VirtualHost>
A new DNS entry is required each time we have a new branch, so I'm trying to mitigate this by providing a dynamic subdomain vhost (see the vhost I have so far). I've gone from not even being able to match /images/ in the url to a permanent redirect loop.
How can I achieve my goal? I know it's a little complex. If I can't do it, I'll just have to write a script that will generate a new vhost each time but a dynamic one that 'just works' would be fantastic. I've put two days into this so far, I'm no sysadmin. Your help would be greatly appreciated.
Resources I have been using:
mod_rewrite official docs - Shows the basics like things on conditions with REWRITE_COND
Sub domain rewriting - A question on subdomain rewriting
Asset rewriting - Another question on rewriting things like images / css / js, which doesn't seem to work for me
It's not a complete answer, but is too long for comment.
The %0 (%0 to %9) in a rewrite rule are back references to captures in the last RewriteCond. It seems to me you wanted instead the host name. Also it seems you miss the "branch" part of the path. In the Asset's rewrite you also throw away the filename part.
# Assets needs to be forwarded - currently not working
RewriteCond %{REQUEST_URI} ^/(css|js|images)/(.*)
RewriteRule .*$ /var/www/vhosts/branch/%{HTTP_HOST}/shared-httpdocs/%1/%2$ [L]
# The HTTP dispatcher - currently not working
RewriteCond %{HTTP_HOST} ^(.*)\.branch\.sandbox\.domain\.com [NC]
RewriteRule ^(.*)$ /var/www/vhosts/branch/%{HTTP_HOST}/applications/portal/dispatchers/http.php [L,QSA,NS,NE,NC]
You can get debugging help also from mod_rewrite dedicated logging with RewriteLog and RewriteLogLevel directives.
Hope this will bring you further.

.htaccess: Redirect depending on accessed url

I want to, in my .htaccess, redirect the user to another url depending on what the user accesses.
In this case, http://example.com/awesome.com and http://awesome.com is the same site, and if the user is accessing http://example.com/awesome.com, I want him or her to be redirected to http://awesome.com.
Is this feasible?
Edit: With the help of answers, I came up with this working solution:
RewriteEngine on
RewriteCond %{HTTP_HOST} !^awesome.com$
RewriteRule ^(.*)$ http://awesome.com/$1 [R=301]
you can use mod_rewrite (apache2 module)
this is the .htaccess that i use in order to redirect from my old domain to my new one (while keeping the link strcture e.g www.domain1.com/link/linkb.html becomes www.domain1.gr/link/linkb.html)
RewriteEngine On
RewriteCond %(www\.)?domain1\.com$ [NC]
RewriteRule .* http://www.domain1.gr%{REQUEST_URI} [R=301,L]
google mod_rewrite for more information (syntax etc)
Not entirely sure about .htaccess, but you could just use server code on your 404 page to redirect them appropriately; this way you could collect stats, setup a toolbar, or whatever other actions you might want to take.
.htaccess is about authorization, not redirection. I recommend you look at the redirection support for Apache (or whatever web server you're using), which is a much better fit for this problem and just make sure your .htaccess/authorization is in line with the target.
This rule should do it:
RewriteRule ^awesome\.example(/.*)?$ http://www.awesome.example$1 [R=301,L]
Check the Redirect & RedirectMatch options in apache. For simple cases, like yours it's simplier than a mod_rewrite.
Redirect /awesome.com http://ww.awesome.com
or
Redirect permanent /awesome.com http://ww.awesome.com
Now, if example.com and awesome.com are on the same apache server and same virtualhost you're maybe mising the named bases virtualhost things and you're maybe trying to make something really more complex than a simple named base virtualhost definition.

Apache .htaccess to redirect index.html to root, why FollowSymlinks and RewriteBase?

In order to redirect all somefolder/index.html (and also somefolder/index.htm) to somefolder/ I use this simple rewrite rule in Apache .htaccess file:
RewriteEngine on
RewriteCond %{THE_REQUEST} ^.*\/index\.html?\ HTTP/
RewriteRule ^(.*)index\.html?$ "/$1" [R=301,L]
This works well!
But at Google groups they suggest to add also:
Options +FollowSymlinks
RewriteBase /
Could anyone be so kind to explain me why would i have to add these last lines, and explain me a bit what they mean and what they do?
Is there a potential secuirty risk in not adding these lines?
Many thanks,
Why they're suggested:
It's suggested that you add Options +FollowSymlinks because it's necessary that symlink following is enabled for mod_rewrite to work, and there's a chance that, while you may be allowed to turn it on, it's not enabled by the main server configuration. I suspect the reason that symlink following is necessary is beause the module makes a number of calls to apr_stat(), which looks like it needs to follow symlinks in order to get file information in all cases.
As for RewriteBase, it's typically not necessary. The documentation goes on about it, but as most people's files do live under the DocumentRoot somewhere, it usually only serves a purpose if you're redirecting externally and you use directory-relative URLs. To illustrate what I mean, consider the following:
RewriteEngine On
RewriteRule ^redirect index.html [R,L]
A request for example.com/redirect will result in an external redirect to example.com/full/path/to/web/root/index.html. The reason for this is that before it handles the redirection, mod_rewrite re-appends the current directory path (which is the default value of RewriteBase). If you modified RewriteBase to be /, then the path information would be replaced with that string, so a request for index.html would now be a request for /index.html.
Note that you could just have done this explicitly on the replace too, regardless of the value of RewriteBase:
RewriteEngine On
RewriteRule ^redirect /index.html [R,L]
...works as intended, for example. However, if you had many rules that needed a common base and were being shifted around between directories, or your content wasn't under the root, it would be useful to appropriately set RewriteBase in that case.
The risk of not using them:
There's absolutely no security risk in not specifying Options +FollowSymlinks, because if you don't and it's not set by the main server configuration, mod_rewrite will always return 403 Forbidden. That's kind of problematic for people trying to view your content, but it definitely doesn't give them any extended opportunity to exploit your code.
Not setting RewriteBase could expose the path to your web content if you had an improperly configured rule set in one of your .htaccess files, but I'm not sure that there's any reason to consider that a security risk.

RewriteRule for mapping x.domain.com to y.domain.com

Is it possible to redirect all requests to x.domain.com/.* to y.domain.com/.* WITHOUT letting this redirection be visible in the url?
I have unsuccessfully tried several things in .htaccess. Just specifying the [L] flag still shows this redirection in the url (as it does when I use the [R] flag additionally).
EDIT: as somebody claimed there being no reason for this, let me give some more information :)
I have one nice url: x.domain.com , which is well known.
Then there are a number of other domains: spring.domain.com , summer.domain.com , autumn.domain.com, winter.domain.com .
Depending on the time of the year, a specific y.domain.com becomes the current one. The x.domain.com should always map to the current one.
EDIT2:
I'll write here, as the code isn't nicely rendered in the comments...
I tried what Arjan suggested:
RewriteCond %{HTTP_HOST} ^x.domain.com$
RewriteRule ^(.*)$ /path/to/y.domain.folder/$1
Unfortunatly though this keeps redirecting forever. :(
Request exceeded the limit of 10 internal redirects due to probable configuration error. Use 'LimitInternalRecursion' to increase the limit if necessary. Use 'LogLevel debug' to get a backtrace.
Putting the [R] flag behind, I see in the url something like:
http://x.domain.com/path/to/y.domain.folder/path/to/y.domain.folder/path/to/y.domain.folder/ ...
Any suggestions?
Now that I can read the errorlogs, I can give a direct response, as what a possible 500 error refers to.
Assuming you have access to the Apache configuration, create the following virtual host for domain x.domain.com. Then simply update y to whatever you need each season.
<VirtualHost ...:80>
ServerName x.domain.com
UseCanonicalName Off
ProxyRequests Off
<Proxy *>
Order Allow,Deny
Allow from all
</Proxy>
ProxyPreserveHost Off
RewriteEngine On
RewriteRule ^$ http://y.domain.com/ [P,NC]
RewriteRule ^/(.*)$ http://y.domain.com/$1 [P,NC]
ProxyPassReverse / http://y.domain.com/
</VirtualHost>
Also to pick up the Alias suggestions, if you have multiple virtual hosts (one for each season) then you could put a server alias into the current domain. E.g.
<VirtualHost ...:80>
ServerName summer.domain.com
ServerAlias x.domain.com
...
</VirtualHost>
<VirtualHost ...:80>
ServerName spring.domain.com
...
</VirtualHost>
...
This would make Apache deliver the summer.domain.com pages if you go to x.domain.com. If your seasonal subdomains depend on the HOST header line to be set correctly (i.e. to season.domain.com) you would need to use the first suggestion above, though.
If these are not hosted on the same server, then you'd need the Proxy flag. This also requires the proxy module to be running. Not tested:
RewriteCond %{HTTP_HOST} ^x.domain.com$
RewriteRule ^(.*)$ http://y.domain.com/$1 [P]
EDIT: Given the edits to your question they're probably just on the same server. So then indeed, as jetru suggested an Alias might do. Or:
# No RewriteCond required; serve all content from other folder:
RewriteRule ^(.*)$ /path/to/y.domain.folder/$1
EDIT: The above would not change the HTTP_HOST header that was sent by the browser (maybe that can be done as well). This implies that it would only work if the subdomains are represented on the file system as separate directories. So, as the .htaccess would then be placed in the directory holding the website for x.domain.com, the RewriteCond wouldn't even be required. Also, the directory for this x.domain.com subdomain would in fact not need any HTML content then; in the end all content would be served from the directory of another subdomain.
EDIT: As the above does not seem to work either, and yields endless rewrite loops even when adding [NS], maybe simply adding [L] helps here:
RewriteRule ^(.*)$ /path/to/y.domain.folder/$1 [NS,L]
Or maybe one can set an environment variable to stop the loop:
RewriteCond %{ENV:MY_VAR} !=1
RewriteRule ^(.*)$ /path/to/y.domain.folder/$1 [E=MY_VAR:1]
But, for both [L] and [E]: I'm just guessing; I've never made mod_rewrite jump into the directory of another virtual host. I am not sure it can be done to start with.
Unfortunately, it's unclear how one would add a new subdomain. If one would just need to create a new directory with the name of the subdomain (without any use of some administrative tool) then the provider might be be using system wide rewriting as well. In fact, even without subdomains the provider might be doing some Mass Virtual Hosting as described in the URL Rewrite Guide.
I guess the best solution would be to change the value of HTTP_HOST on the fly, to solve issues with any system wide rewriting. Maybe the following is allowed to achieve that:
RewriteCond %{HTTP_HOST} ^x.domain.com$
RewriteRule ^(.*)$ /path/to/y.domain.folder/$1 [E=HTTP_HOST:y.domain.com]
Again, as the above would only be present in the .htaccess in the x.domain.folder, the RewriteCond is probably not needed at all.
Have you tried
Alias /dir/file.html /full/path/to/other/file.html
??
To my knowledge and testing with firebug a redirect via .htaccess is always announced to the client and it's up to him how to proceed. It is therefore not an alternative to some sort of SSI functionality. To prevent a "fake" address modern browser should always make the REAL address visible to the user, however I think I have seen some misbehavior in programs like "feeddemon" where IE is embedded. If you - for whatever reason - really want to show content from one subdomain on another you can try using Javascript or (i)frames on the user side or some include functionality on the server site (eg. file_get_contents with php). However, I don't recommend this.

Problems redirecting old domain to new with Apache and htaccess

My homepage is located at www.nazgulled.net and I bought a new domain which is www.ricardoamaral.net. Both these domains point to the same exact server.
I'm having two problems with the redirection, my current code is this:
RewriteCond %{HTTP_HOST} ^(www\.)?nazgulled\.net [NC]
RewriteRule ^(.*)$ http://www.ricardoamaral.net/$1 [L]
For now I'm just testing but the idea is to replace [L] with [L,R=301] when I'm ready to move the whole thing, just so you know.
Anyway...
1) This is not working, when I try it, I can't access "nazgulled.net", it gives me a "server internal error" and I don't understand why... I don't understand why because if replace "ricardoamaral.net" by "google.com", the redirect works just fine :/
2) I have a few subdomains and I would like to redirect everything in those too. My first choice is to add different rewrite conditions/rules for each of the subdomains but that takes a lot of manual code and if the user types some subdomain that doesn't exist, they don't be redirect it and I also want that.
I think for your situation creating separate vhosts would be the ideal fit. What I do often is place domains that are being redirected on the same server but in a different folder to keep the www folder clean, for instance. My main site would be here:
/var/www/example.com/public
For all my redirects I would place them like so:
/var/www/redirects/example-2.com/public
Within each public folder of the redirected sites you would add this line to your .htaccess file
RedirectMatch permanent /.* http://example.com/
For 1, you can use something like this instead:
<VirtualHost *:80>
ServerAdmin webmaster#nazgulled.net
ServerName nazgulled.net
ServerAlias www.nazgulled.net
Redirect permanent / http://www.ricardoamaral.net/
</VirtualHost>
I use a similar configuration and it works perfectly, keeping query parameters, paths, etc.
Regarding your own rewrite rule, I want to note that you may lose your query params if you don't include QSA.
To diagnose internal server errors, just have a look at the log file provided by your ErrorLog directive within your vhost, or a global one, depending on your configuration. It should give you the exact reason for the error.
This is best solutions. Create a notepad file and save it as .htaccess if you do not already have an existing one.
Update the .htaccess file with the following code and save
Options +FollowSymLinks
RewriteEngine on
RewriteRule (.*) http://new-domain.com/$1 [R=301,L]