difference between RewriteRule ^(.*)$ & RewriteRule (.*)$ - .htaccess

When moving all pages from old domain to new domain, i noticed some people added a ^and other not in rewriterule
What is the different between
RewriteRule ^(.*)$ http://mynewdomain.com/$1 [R=301,L]
and
RewriteRule (.*)$ http://mynewdomain.com/$1 [R=301,L]
thank you.

They are both wrong. There is no need to match anything in a backreferennce because Apache has a built in variable for the current URL: %{REQUEST_URI}.
RewriteRule .? http://www.newdomain.com%{REQUEST_URI} [L,R=301]
As for your question, the meaning of ^ is 'matches at the start of the URLand$` is 'matches at the end of the URL'. This is probably easiest by example.
^welcome/ matches the url /welcome/a/b/c, /welcome/b/c/d, etc, anything that starts with /welcome
welcome$ matches /a/b/welcome, /a/something/welcome, etc, anything that ends with a 'welcome'
The first RewriteRules you present in your question is 'An URL that has a start and an end and something inbetween', while the second one is 'a URL that has some text and then ends'. Both expressions are very generic and match anything you throw at it.

It is always better to use start and end anchors (^ and $) wherever possible like ^(.*)$ but in the 2 cases you listed both rules will behave similar.

Related

htaccess redirect "/?id=(.*)", but only at the root?

I have been unable to get a redirect to work. The behavior I was hoping to have would redirect from:
www.mysite.com/?id=12345
to
www.mysite.com/?other_id=12345
The rule I wrote seems to grab any url matching the very end like:
www.mysite.com/directory/another/?id=12345
I just want this to work at the root level, not all levels.
The rule I currently have is as follows:
RewriteCond %{QUERY_STRING} ^(.*&)?id=([^&]+)$
RewriteRule ^(.*)$ http://%{SERVER_NAME}/?other_id=%2 [R=301,L]
For some reason I had to include the first regex as it was not accepting it without it. Without the first ^(.*&) It kept saying that the site was creating a redirect that would not work and bombing out, which may be a part of my problem.
IS there a better way to write this rule? or is a root level match alone not possible?
Thank you,
Silvertiger
Change your regex from ^(.*)$ to `^$``:
RewriteCond %{QUERY_STRING} ^(.*&)?id=([^&]+)$
RewriteRule ^$ http://%{SERVER_NAME}/?other_id=%2 [R=301,L]
The ^(.*)$ regex matches any request URI, so /, and /foo and /dir1/dir2/dir3/file.txt will all match. But the ^$ only matches /.

.htaccess 301 redirect problem

i try to redirect url's like:
example.com/video/1640/video-name
to
example.com/video/1640/video-name/
i've tried with:
RewriteRule ^video/([^/]*)/([^/]*)/$ video.php?id=$1&title=$2 [L]
RewriteRule ^video/([^/]*)/([^/]*)$ /video/([^/]*)/([^/]*)/ [R=301,L]
but it is not working
my currently htaccess file has only the first line:
RewriteRule ^video/([^/]*)/([^/]*)/$ video.php?id=$1&title=$2 [L]
and videos only loads at
example.com/video/1640/video-name/
url type
i want to redirect the non-backslash url type
example.com/video/1640/video-name
to the correct one (the one with the backslash)
How can i do this?
Your second rule should be RewriteRule ^video/([^/]*)/([^/]*)$ /video/$1/$2/ [R=301,L]
Or you could forgo the redirect totally, and just say RewriteRule ^video/([^/]*)/([^/]*)/?$ video.php?id=$1&title=$2 [L] which will allow both to view your video.
Update FallingBullets is right (see the comments on this answer), his answer better suites the OP's problem, so please ignore this answer (I am leaving it for reference, though).
Maybe you simply have to prefix your pattern with a /?? E. g.
RewriteRule ^/?video/([^/]*)/([^/]*)/$ video.php?id=$1&title=$2 [L]
RewriteRule ^/?video/([^/]*)/([^/]*)$ /video/([^/]*)/([^/]*)/ [R=301,L]
# ^ these ones
instead of
RewriteRule ^video/([^/]*)/([^/]*)/$ video.php?id=$1&title=$2 [L]
RewriteRule ^video/([^/]*)/([^/]*)$ /video/([^/]*)/([^/]*)/ [R=301,L]
since you are anchoring the pattern at the beginning of the path (using ^).

Fixing Rewrite Rules and Conditions In HTACCESS file

Well lets say I have this follow code in my htaccess file,
Options +FollowSymlinks
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.(.*) [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,NC,L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^([^/]+)$ $1.php
RewriteRule ^forums/([0-9]+) forums.php?category=$1 [NC]
I was wondering how would I, with the above code, redirect certain extensions in a url to my websites 404 page.
For instance, if this link mywebsite.com/forums has any extension at the end of it such as .asp, .php, .html, and so forth it then would get redirected to my 404 page.
And on a quick side note how can I limit the last RewriteRule to only a certain forward slash where mywebsite.com/forums/2 would show the page fine and anything after that certain limit such as mywebsite.com/forums/2/so on... would be redirected to my 404 page.
Anyone have any ideas?
If I understand the question properly, then you need to firm up the regular expressions to only match the patterns you really want - at the moment, they're a bit too lenient for your needs.
For example:
RewriteRule ^([^/]+)$ $1.php
This will match anything without a trailing slash, whereas if you wanted to restrict it to only match, say, things without a trailing slash and consisting of alphanumeric characters, then you might do this:
RewriteRule ^([a-zA-Z0-9]+)$ $1.php
(You could achieve the same effect for certain extensions only by using a lookahead assertion, but that complicates your regular expression. I feel it's probably saner (and easier on the mind) to think about the patterns you really want matched, and then express those up-front.)
Likewise, your latter example:
RewriteRule ^forums/([0-9]+) forums.php?category=$1 [NC]
will match anything which starts with the string forums/, followed by one or more digits, whether or not there's anything after that. Adding an end anchor ($) as you have above
RewriteRule ^forums/([0-9]+)$ ...
will assert that the string ends after the digits.
This relies on the fact that if mod_rewrite can't find a match, it won't attempt any rewrites, and will (in the absence of any explicit resource at that path) fall through to Apache's 404 handling, which is then up to you to override.

mod_rewrite regex (too many redirects)

I am using mod_rewrite, to convert subdomains into directory urls. (solution from here). When I explicity write a rule for one subdomain, it works perfectly:
RewriteCond %{HTTP_HOST} ^[www\.]*sub-domain-name.domain-name.com [NC]
RewriteCond %{REQUEST_URI} !^/sub-domain-directory/.*
RewriteRule ^(.*) /sub-domain-directory/$1 [L]
However, if I try to match all subdomains, it results in 500 internal error (log says too many redirects). The code is:
RewriteCond %{HTTP_HOST} ^[www\.]*([a-z0-9-]+).domain-name.com [NC]
RewriteCond %{REQUEST_URI} !^/%1/.*
RewriteRule ^(.*) /%1/$1 [L]
Can anyone suggest what went wrong and how to fix it?
Your second RewriteCond will never return false, because you can't use backreferences within your test clauses (they're compiled during parsing, making this impossible since no variable expansion will take place). You're actually testing for paths beginning with the literal text /%1/, which isn't what you wanted. Given that you're operating in a per-directory context, the rule set will end up being applied again, resulting in a transformation like the following:
path -> sub/path
sub/path -> sub/sub/path
sub/sub/path -> sub/sub/sub/path
...
This goes on for about ten iterations before the server gets upset and throws a 500 error. There are a few different ways to fix this, but I'm going to chose one that most closely resembles the approach you were trying to take. I'd also modify that first RewriteCond, since the regular expression is a bit flawed:
RewriteCond %{HTTP_HOST} ^([^.]+)\.example\.com$ [NC]
RewriteCond %1 !=www
RewriteCond %1#%{REQUEST_URI} !^([^#]+)#/\1/
RewriteRule .* /%1/$0 [L]
First, it checks the HTTP_HOST value and captures the subdomain, whatever it might be. Then, assuming you don't want this transformation to take place in the case of www, it makes sure that the capture does not match that. After that, it uses the regular expression's own internal backreferences to see if the REQUEST_URI begins with the subdomain value. If it doesn't, it prepends the subdomain as a directory, like you have now.
The potential problem with this approach is that it won't work correctly if you access a path beginning with the same name as the subdomain the request is sent to, like sub.example.com/sub/. An alternative is to check the REDIRECT_STATUS environment variable to see if an internal redirect has already been performed (that is, this prepending step has already occurred):
RewriteCond %{HTTP_HOST} ^([^.]+)\.example\.com$ [NC]
RewriteCond %1 !=www
RewriteCond %{ENV:REDIRECT_STATUS} =""
RewriteRule .* /%1/$0 [L]

Ending with period using Mod Rewrite

I would like to know how to allow periods at the end on my url's. Currently if I had the url:
http://www.mydomain.com/Page/I.D.K.
The page grabbing the information would return
Title: I.D.K (Without the ending period)
This also happens with other punctuation and it is effecting my pages displaying information wrongly. Thanks for looking, hope somebody knows the solution.
I am using the following in my htaccess file:
RewriteRule ^([^/.]+)/?$ /index.php?Page=$1 [L]
RewriteRule ^([^/.]+)/([^/]+)/?$ /index.php?Page=$1&Level1=$2 [L]
RewriteRule ^([^/.]+)/([^/]+)/([^/]+)/?$ /index.php?Page=$1&Level1=$2&Level2=$3 [L]
RewriteRule ^([^/.]+)/([^/]+)/([^/]+)/([^/]+)/?$ /index.php?Page=$1&Level1=$2&Level2=$3&Level3=$4 [L]
Ok problem virtually solved. The & still breaks my strings if I try doing Artist1 & Artist2 but I will just use string replace to replace that symbol with something else. Anyway, to allow punctuation anywhere, even at the end, I replaced all + with * in my rewrite rules. Here is how it looks now:
RewriteRule ^([^/.]*)/?$ /index.php?Page=$1 [L]
RewriteRule ^([^/.]*)/([^/]*)/?$ /index.php?Page=$1&Level1=$2 [L]
RewriteRule ^([^/.]*)/([^/]*)/([^/]*)/?$ /index.php?Page=$1&Level1=$2&Level2=$3 [L]
RewriteRule ^([^/.]*)/([^/]*)/([^/]*)/([^/]*)/?$ /index.php?Page=$1&Level1=$2&Level2=$3&Level3=$4 [L]
Hope this helps some other people with similar problems.
I'm assuming this is located in http://www.mydomain.com/. Here's what I'd use for the second Rule (which can then be transposed to the other rules):
RewriteRule ^([A-Za-z0-9\-,]+)/([A-Za-z0-9.\-,]+)/?$ /index.php?Page=$1&Level1=$2 [L]
That will match the following: (and will allow for hyphens, commas, and periods for Level1)
IDK/Jump.ing.
IDK/Jump.ing./
But not:
S$!LV/J
I try and whitelist my options (something like /[A-Z]/), rather than blacklist them (/[^3-5]/). I'm sure there are arguments for both options, but I like whitelisting mostly because I have control over what can be used. If I don't include it in my list, it's not a valid option. Of course, if you're accepting a LOT of options, then this could make for some very long character classes or whatnot. What if someone went to http://www.mydomain.com/Page/I.D.K.&somevariable=somevalue ? It could potentially break your script (if the person is smart). Your RewriteRule would send them to /index.php?Page=Page&Level1=I.D.K.&somevariable=somevalue. Not at all what you anticipated happening.

Resources