Extract part of server name in Apache RewriteRule - regex

Let's suppose that I have a file in the filesystem like this:
/documentroot/domains/foo/files/resource.html
I want to write a rule so that http://foo.example.com/resource.html serves the file /domains/foo/files/resource.html. But if the request URL is http://bar.example.com/resource.html, it should look inside /domains/bar/files/resource.html. What I've accomplished so far is this, which works correctly:
RewriteEngine On
RewriteCond "%{DOCUMENT_ROOT}/domains/foo/%{REQUEST_URI}" -f
RewriteRule ^ domains/foo/%{REQUEST_URI} [QSA,L]
How can I generalize this, for any domain name? I was thinking of applying a regular expression to the %{SERVER_NAME} variable, but I can't find a way to achieve this.

You can use this rule:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{HTTP_HOST} ^(?!www\.)([^.]+)\. [NC]
RewriteRule !^domains/ domains/%1/files%{REQUEST_URI} [L,NC]

Related

Rewrite rule in htaccess mapping to wrong url

I'm having an issue on this. Say, I have mypage.com/search/mykey and i want it to map to mypage.com/search?key=mykey. This is my .htaccess rule:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^search/(.*)$ /search?key=$1 [L]
# Pass all requests not referring directly to files in the filesystem to
# index.php.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^ index.php [L]
However, in the logs I can see that it's mapping to mypage.com/search/mykey?key=mykey.
Edit:
To give more context on what can be the issue, I included the rewrite rule just below the one I wrote. Don't know if they're messing each other.
Thanks in advance for all your help.
You could try using RewriteBase "/" in that way apache knows that relative files must be within the rewrite base path.
RewriteBase "/"
...
RewriteRule ^search/(.*)$ search?key=$1 [L]
...
Note: RewriteBase affects all relative files named in rewrite rules

htaccess regex to grab additional field

I have the following regex although it only picks one variable and puts that in user like user contains user/url, how would I modify this to grab the url variable seperately in $2.
RewriteCond %{HTTP_HOST} ^(^.*)\.example.com$ [NC]
RewriteRule ^(.+/?[^/]*)$ http://example.com/index.php?sub=%1&url=$1 [P,NC,QSA,L]
I need this to translate
http://sub.example.com/user/url
to
http://example.com/index.php?sub=%1&user=$1&url=$2
Your regex to capture 2 values from RewriteCond and RewriteRule doesn't seem correct.
You may use:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{HTTP_HOST} ^([^.]+)\.example\.com$ [NC]
RewriteRule ^([^/]+)(?:/([^/]+))?/?$ http://example.com/index.php?sub=%1&user=$1&url=$2 [P,NC,QSA,L]
I assume you have mod_proxy setup since you're using P flag.

htaccess RewriteCond: Why doesn't a server variable match itself?

Perhaps a better question would be, is there any way to use server variables in the matching string?
For example, I can't understand why this fails to match:
RewriteCond %{REQUEST_URI} %{REQUEST_URI}
First, two points.
I know this condition servers no purpose as is.
I know I have poor knowledge of both htaccess and regex.
What I want is to generically turn this URL www.example.com/dir/path/info into www.example.com/dir?foo=/path/info for bootstrapping.
I tried to accomplish this by removing the extra path info from the deepest actual directory in the URL. I was trying this code to test the premise:
RewriteEngine On
Options -Multiviews -Indexes +FollowSymLinks
RewriteBase /
DirectorySlash Off
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} (.+)%{PATH_INFO}
RewriteRule ^(.+?) index.php?dir=%1&path=%2 [L]
No luck. To troubleshoot I reduced it to this:
RewriteCond %{PATH_INFO} (.+)
RewriteRule ^(.+?) index.php?dir=%1 [L]
As expected the query returned foo='/path/info'
So I tried this which I thought would match no matter what:
RewriteCond %{PATH_INFO} %{PATH_INFO}
That failed so as a last attempt, I tried capturing the string:
RewriteCond %{PATH_INFO} (.+)
RewriteCond %{PATH_INFO} %1
That also failed to find a match which has me baffled. %1 should be the complete %{PATH_INFO} string. How could it not match itself???
I don't think it matters but I'm using XAMPP on Windows7 in FastCGI.
Rewrite pattern params only allow regex (tho Condpattern also has special flags for tests and comparisons):
RewriteCond TestString CondPattern
RewriteRule Pattern Substitution
Server variables like %{REQUEST_URI} can only be used in Teststring and Substitution. The following docs outline this usage:
http://httpd.apache.org/docs/2.4/mod/mod_rewrite.html#rewritecond
http://httpd.apache.org/docs/2.4/mod/mod_rewrite.html#rewriterule
If this will go in your main .htaccess, perhaps try:
RewriteCond %{REQUEST_URI} !index\.php$
RewriteRule ^([^/]+)/(.+)$ index.php?dir=/$1&path=/$2 [L]
Two more Example:
Sample1
RewriteBase /
RewriteRule ^(.+/)?index.php(/.+) index.php?dir=/$1&path=$2 [R,L]
Sample2
RewriteBase /
RewriteRule ^((.+/)?index.php)(/.+) $1?path=$3 [R,L]
Sample3
RewriteBase /
RewriteRule ^(.+/)?(.+\.php)(/.+) $1$2?foo=$3 [R,L]
these all do external rewrite so you can see result in the browser address. To revert to internal rewrite, just remove [R] flag
Ok, I found a way to accomplish this goal.
Basically I was trying to compare two server variables. htaccess won't do that. I wanted to extract part of a "pretty" url which points to an actual file or folder. The variable ${SCRIPT_URL} should do that, but it is either depreciated or not reliable. The work around is to put both variables in the test string and use a regex back reference to find the point of duplication.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteCond %{REQUEST_URI}%{PATH_INFO} (.*?)(/.+)\2$
RewriteRule ^(.*)$ %1.php?strappath=%2 [QSA,END]
In the above example %1 will be the uri of the file and %2 will be the remaining path after the URI, duplicating %{PATH_INFO}.
Follow with this rule for when there is no extra path info
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+?)$ $1.php [QSA,END]
If no .php file is found, I want the index of that directory and add the un-found file name to the pathinfo. This is a bit trickier.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php !-f
RewriteCond %{REQUEST_FILENAME} ^(.*)(/.+)$
RewriteCond %1 -d
RewriteCond %1/index.php -f
RewriteCond %{REQUEST_URI}%{PATH_INFO} ^(.*?)(/.+)\2$ [OR]
RewriteCond %{REQUEST_URI} ^(/.+)(/.+)?$
RewriteCond %1 ^(.*)(/.+)$
RewriteRule ^(.*)$ %1/index.php?strappath=%2%{PATH_INFO} [QSA,END]
The above section fails to catch urls that point directly to an existing folder with an index.php, so to catch those:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_FILENAME}/index.php -f
RewriteCond ^(.+)$ $1/index.php [QSA,END]
I doubt anyone ever finds this useful but I've seen variations of this question asked over and over with no working solution given.

URL Rewriting with / or not

Im trying to fix this warning:
Avoid use of file extensions wherever possible.... Consider URL rewriting as an effective and transparent means of creating appropriate URLs
I added to my .htaccess file this:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^(.*)$ $1.html
Its working fine on example.com/page but Im getting an Internal Server Error on example.com/page/
Any ideas?
Change your regex to allow an optional trailing slash:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$1\.html -f [NC]
RewriteRule ^(.+?)/?$ /$1.html [L]

htaccess external rewrite / internal redirect

There are two things that I would like to achieve with .htaccess file.
The first one is
www.hostname.com/index.php?question -> www.hostname.com/question
www.hostname.com/index.php?myinfo -> www.hostname.com/myinfo
www.hostname.com/index.php?notification -> www.hostname.com/notification
so I use external rewrite to re-express on the URL as following.
RewriteCond %{THE_REQUEST} /(index.php)\?([^&]+)\ HTTP
RewriteRule ^ /%2? [R=301,L]
Now the above statement correctly displays as I want. The problem is to internally convert back when a condition is satisfied. The condition is if %{THE_REQUEST} is equal to any character after '/'.
RewriteCond %{REQUEST_URI} ^/(.*)$ [NC]
RewriteRule ^(.*)$ index.php?$1 [NC,L]
So that my php code can recognize the $_GET parameter. Here, even though the condition is satisfied it will not process the RewriteRule.
The second problem is
www.hostname.com/index.php?category=spo -> www.hostname.com/category/spo
www.hostname.com/index.php?category=ite -> www.hostname.com/category/ite
www.hostname.com/index.php?category=gam -> www.hostname.com/category/gam
The conversion is completed using exteral rewrite:
RewriteCond %{THE_REQUEST} /(index)\?category=([^&]+)\ HTTP
RewriteRule ^ category/%2? [R=301,L]
Again, I'd like to convert back whatever is written in the URL back to the original format internally so I use the following condition to differentiate from the previous case,
RewriteCond %{REQUEST_URI} ^/category/(.*)$
RewriteRule ^category/(.*)/?$ index.php?category=$1 [NC,L]
my php code cannot recognize the $_GET parameter and variable. When I use htacces tester, it says it should work but it doesn't. http://martinmelin.se/rewrite-rule-tester/
How do I fix this problem? OR is there any easier way to accomplish this?
Thank you
Try these rules:
RewriteEngine On
RewriteCond %{THE_REQUEST} \s/index\.php\?category=([^&\s]+) [NC]
RewriteRule ^ /category/%1? [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^category/([^/]+)/?$ /index.php?category=$1 [NC,L,QSA]
RewriteCond %{THE_REQUEST} \s/index\.php\?([^&\s]+) [NC]
RewriteRule ^ /%1? [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/?$ /index.php?$1 [QSA,L]