apache mod rewrite with the_request - mod-rewrite

I want to do the following with apache (mod rewrite).
if the user requests http://hostname.tld/index.php/folder/subfolder i want it to redirect (with a R=301) to http://hostname.tld/folder/subfolder.
if the user requests http://hostname.tld/folder/subfolder the request should internally be rewritten to index.php/folder/subfolder.
To prevent an endless redirect the first rule should check for %{THE_REQUEST}. The problem here is that I am unable to append "folder/subfolder" with a regex. How should I do this?
For the second rule I have this (and seems to work).
RewriteCond %{HTTP_HOST} hostname.tld [NC]
RewriteRule ^(.*)$ index.php [QSA,L]
The first one is still a problem.
I think the first one should be something like
RewriteCond %{THE_REQUEST} (.*)index.php(.*) [NC]
RewriteRule /index.php/$ http://hostname.tld/$1 [R=301,QSA,L]
But that is not really it.

The first should be.
RewriteCond %{HTTP_HOST} ^hostname\.tld$ [NC]
RewriteCond %{THE_REQUEST} index\.php [NC]
RewriteRule ^index.php/(.*)$ http://hostname.tld/$1 [R=301,L]
I also see that your second rule redirects http://hostname.tld/folder/subfolder to http://hostname.tld/index.php (not http://hostname.tld/index.php/folder/subfolder). But as long as that works it's fine, as this it also prevents the redirect loop.
But just in case, here is the solution to add the folder/subfolder part:
RewriteCond %{HTTP_HOST} ^hostname\.tld$ [NC]
RewriteCond $1 !^index\.php
RewriteRule ^(.*)$ index.php/$1 [QSA,L]

Related

RewriteCond %{REQUEST_URI} not working

I am trying to redirect all requests coming in to the web server as http://portal.company.com/legacy to http://portal.company.com/wps/portal/public/legacy/legacyportlet with the following rule, but it is not working as expected.
RewriteEngine on
RewriteCond %{HTTP_HOST} ^portal\.company\.com$ [NC]
RewriteCond %{REQUEST_URI} ^/legacy$ [NC]
RewriteRule ^(.*)$ /wps/portal/public/legacy/legacyportlet$1 [NC,L,PT]
I have also tried
RewriteCond %{HTTP_HOST} ^portal\.company\.com$ [NC]
RewriteRule ^/legacy /wps/portal/public/legacy/legacyportlet [NC,L,PT]
Any help would be greatly appreciated!
Thanks
It doesn't look like your source or target URLs change in any way, so possibly you're better off using Apache's basic Redirect directive which just redirects one URL to another.
Use this rule:
RewriteCond %{HTTP_HOST} ^portal\.company\.com$ [NC]
RewriteRule ^legacy/?$ /wps/portal/public/legacy/legacyportlet [NC,L]
Remember that in .htaccess RewriteRule doesn't match leading slash of URI.

Mod Rewrite won't redirect subdomains to new URL format

I'm changing all my subdomains to a single domains.
However, in order no to lose all my SEO I need to do some 301 redirections. My problem is that I have about 10.000 subdomains (it's a website about cities and each city is a subdomain) so I need to make a generic rewrite rule in order to make the new URLs (otherwise my htaccess will be too big).
I tried doing it myself but for some reason, it's doing what it wants to (so I guess I'm doing something wrong). Here is my code:
RewriteCond %{HTTP_HOST} ^(.*)\.domain\.com/b/^(.*)
RewriteRule ^(.*) http://domain.com/city/$1/b/$2 [R=301,L]
RewriteCond %{HTTP_HOST} ^(.*)\.domain\.com
RewriteRule ^(.*) http://domain.com/?multi_city=$1 [R=301,L]
This is what happens with these two rules.
city.domain.com --> domain.com/?multi_city=/
city.domain.com/b/place --> domain.com/?multi_city=/b/place
What am I doing wrong?
Thanks in advance.
So, after many hours, I finally fixed it doing this:
RewriteCond %{HTTP_HOST} ^(.+)\.mydomain\.(.*)
RewriteCond %{REQUEST_URI} ^/b
RewriteRule ^(.*)$ http://mydomain.%2/city/%1/$1 [R=301,L]
RewriteCond %{HTTP_HOST} ^(.+)\.mydomain\.(.*)
RewriteCond %{REQUEST_URI} ^/event
RewriteRule ^(.*)$ http://mydomain.%2/city/%1/$1 [R=301,L]
RewriteCond %{HTTP_HOST} ^(.+)\.mydomain\.com
RewriteRule ^(.*)$ http://mydomain.com/?multi_city=%1 [R=301,L]
This way I can redirect places and events first and if the URL is not in that format then it will go to the different format URL. It's probably not the most efficient solution but it works for me. Hope this helps to someone else.
I think the first RewriteCond it's wrong:
RewriteCond %{HTTP_HOST} ^(.*)\.domain\.com/b/^(.*)
The '^' symbol says that the string start, it's not part of the group, so I think that you will try:
RewriteCond %{HTTP_HOST} ^(.*)\.domain\.com/b/(.*)
Maybe, it will be better:
RewriteCond %{HTTP_HOST} ^(.*)\.domain\.com/b/([a-zA-Z0-9\-]+)
I'm doing it without testing, if it doesn't work I will make tests later and I'll answer you.

Apache mod_rewrite friendly URLs with corresponding 301 redirects

The Problem:
Been spinning my wheels and reading up on this one for awhile and looking for some help now. I'm looking to take a group of non-friendly URLs (there are actually more "groups" but this should me for an example):
domainname.com/?section=zebras
domainname.com/?section=monkeys&id=555
and turn them into friendly URLs, as well as do a 301 on the old versions, so that any old bookmarks (and search engines) will still resolve them. The new format I'm looking for would be:
domainname.com/zebras/
domainname.com/monkeys/555
I'm fully intending to write separate RewriteCond/RewriteRule combinations for each of those scenarios, so I don't necessarily need a super-rule that catches all my scenarios. Oh and this is all in .htaccess.
My Progress:
I was originally getting into a redirect loop because I was just doing two RewriteRules back to back - one for the friendly URL and one for the 301 redirect. Came across my favorite way (so far) around the redirect loop which works (for my scenario #1 at least):
RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteCond %{QUERY_STRING} ^section=zebras$ [NC]
RewriteRule ^.*$ http://www.domainname.com/zebras/? [R=301,NC,L]
RewriteRule ^zebras/$ /index\.php?section=zebras [NC,L]
However, I'd like to have something that works for more than just "zebras" (for instance, I'd like it to work for "lions" as well), so I'm trying to make that more generic. What I am trying now looks like this:
RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteCond %{QUERY_STRING} ^section=([a-z]+)$ [NC]
RewriteRule ^section=([a-z]+)$ http://www.domainname.com/$1/? [R=301,NC,L]
RewriteRule ^([a-z]+)/$ /index\.php?section=$1 [NC,L]
However, this doesn't work. I think I have something "not quite right", I just can't tell what it is - there's something I'm missing or formatting incorrectly somewhere. Sorry in advance for the lengthy description, just wanted to be clear.
Do this:
RewriteEngine on
RewriteBase /
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(\.\w+|/)$
RewriteRule (.*) /$1/ [R,L]
RewriteCond %{QUERY_STRING} ^section=([a-z]+)$ [NC]
RewriteRule ^ /%1/? [R=301,NC,L]
RewriteRule ^([a-z]+)/$ /index\.php?section=$1 [NC,L]
RewriteCond %{QUERY_STRING} ^section=([a-z]+)&id=(\d+)$ [NC]
RewriteRule ^ /%1/%2/? [R=302,NC,L]
RewriteRule ^([a-z]+)/(\d+)/$ /index\.php?section=$1&id=$2 [NC,L]
Description
Prevents looping:
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ - [L]
Prevents trailing slash problem:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(\.\w+|/)$
RewriteRule (.*) /$1/ [R,L]
Handles rewrites with only section=([a-z]+) in them:
RewriteCond %{QUERY_STRING} ^section=([a-z]+)$ [NC]
RewriteRule ^ /%1/? [R=302,NC,L]
RewriteRule ^([a-z]+)/$ /index\.php?section=$1 [NC,L]
Handles rewrites with only section=([a-z]+)&id=(\d+) in them:
RewriteCond %{QUERY_STRING} ^section=([a-z]+)&id=(\d+)$ [NC]
RewriteRule ^ /%1/%2/? [R=302,NC,L]
RewriteRule ^([a-z]+)/(\d+)/$ /index\.php?section=$1&id=$2 [NC,L]
mistake in your rules:
section=([a-z]+) is not available in the URI part. So, RewriteRule ^section=([a-z]+)$ never matched.

How mod_rewrite can add subdomain?

RewriteEngine On
RewriteRule ^/ai?$ /Market/publish.jsp [QSA,L,PT]
RewriteRule ^/ar?$ /Market/MailDispatch [QSA,L,PT]
RewriteCond %{HTTP_HOST} !^web\.example\.com [NC]
RewriteCond %{HTTP_HOST} !^$
RewriteRule ^/(.*) http://web.example.com/$1 [L,R]
#How skip www\. to web\. for this 1 ?
#RewriteRule ^/vi/?([0-9]+)\.htm$ /Market/vi.do?id=$1 [PT,L]
RewriteRule ^/li /Market/list.do [QSA,PT,L]
RewriteRule ^/vi/locations.jsp /Market/locations.jsp [PT,L]
ErrorDocument 404 /notfound.html
Nearly undoable(?) I try http://example.com/vi/{N}.htm should redirect to http://web.example.com/vi/{N}.htm where N is dynamic ID.
Seen mod_rewrite with subdomain and url pattern
There is no clear way to make eg http://example.com/vi/1096.htm pass up to next version http://web.example.com/vi/1096.htm where number is dynamic. I tried
A rule with the following scheme should do it:
RewriteCond %{HTTP_HOST} ^example\.com$
RewriteRule ^/vi/\d+\.htm$ http://web.example.com%{REQUEST_URI} [L,R=301]
It’s important to put this rule in front of those rules that do an internal redirect. Otherwise an already internally rewritten URL could be rewritten externally.
If you want to use this rule in a .htaccess file, remove the leading slash from the pattern in RewriteRule.

How do I write a custom mod_rewrite .htaccess file for CakePHP routing?

I've rewritten my web app using CakePHP, but now I need to have my old formatted urls redirect to my new url format. I can't seem to add my own custom mod rewrite rule. I've added it above the main cakephp rewrite rule, but I'm getting an infinite redirect loop. I just want http://mysite.com/index.php?action=showstream&nickname=user to redirect to http://mysite.com/user before the cakephp rewrite happens.
EDIT: Ok, so now when the condition is met it's redirecting but it's appending the original query string to the end. I'm assuming that's due to the QSA flag in CakePHP rewrite rules, but I was under the impression the "L" in my rule would stop that from executing...
RewriteEngine On
RewriteCond %{QUERY_STRING} ^action\=showstream&nickname\=(.*)$
RewriteRule ^.*$ http://mysite.com/%1 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
When you do a capture inside the RewriteCond line instead of the RewriteRule, you have to reference the capture with %N instead of $N. That is, your RewriteRule line should be:
RewriteRule ^index.php$ /%1 [R=301,L]
Try to test the request line (THE_REQUEST) to see what URI originally has been requested:
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /index\.php
RewriteCond %{QUERY_STRING} ^action=showstream&nickname=([^&]*)$
RewriteRule ^index\.php$ /%1? [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* index.php?url=$0 [QSA,L]
But maybe it would be easier to do this with PHP.

Resources