mod_rewrite RewriteCond problem - mod-rewrite

In my .htaccess file I have the following rules:
RewriteEngine on
RewriteBase /myblog.com/
RewriteRule ^author/([^/]*)/?([^/]*)/?$ blog/author.php?author=$1&contactid=$2 [L]
RewriteRule ^blog/([^/]*[^/index.php])/?([^/]*)/?([^/]*)/?$ blog/index.php blog=$1&category=$2&article=$3 [L]
My problem is that a request like this myblog.com/author/Jim+Jones/28 is getting redirected to the following rule, even though I have a [L] flag there?
How can I exclude the second rule from firing when "/author/" appears in the URL?
Many thanks, Jason

/author/Jim+Jones/28 shouldn't get caught by any of these as neither of your rules catch URLs starting with / and the ^ at the start of you regex-es clearly stats that for the first rule it must start with 'author/' (note no / at the start).
UPDATE:
What I think is happening is that requests like myblog.com/author/Jim+Jones/28 are being rewritten twice. First by the first rule and then by the second one. If that's the case you'll need to make the 2nd rule more restrictive. Don't let it rewrite requests that have author.php in them for example.
UPDATE 2:
OK, so what would probably be the best in your case is to add a condition for the 2nd clause:
RewriteEngine on
RewriteBase /myblog.com/
RewriteRule ^author/([^/]*)/?([^/]*)/?$ blog/author.php?author=$1&contactid=$2 [L]
RewriteCond %{THE_REQUEST} !(author\.php)
RewriteRule ^blog/([^/]*[^/index.php])/?([^/]*)/?([^/]*)/?$ blog/index.php?blog=$1&category=$2&article=$3 [L]

Related

Mod_Rewrite Difference between [L] and [R]

I am attempting to rewrite any URL with "_excaped_fragment_=/some/directory" to "/some/directory?ajax=1". The code below is working correctly but i would like to do it without the redirect. This is a Wordpress site.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
AddDefaultCharset UTF-8
RewriteCond %{QUERY_STRING} ^_escaped_fragment_=(.*)$
RewriteRule (.*) %1?ajax=1 [L,R=301]
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
If I remove "R=301" and just leave the "L" it does not work. I have read about [L] not stopping when from .htaccess, but i actually do not want it to stop. I would like it to just change the URL then go through the regular Wordpress rewrite.
Any ideas? Let me know if you need more information.
Edit:
Wanted to add an answerable question. Why does a redirect work and no redirect not work? Does the URL get changed as it works its way down the file or only on the last rule?
The [L] will stop any further processing in .htaccess if the rule matched.
The way you have this written the [L] will do that, but then you add [R=301] which is a redirect. That will cause the request to be sent back to the "top of the stack" in Apache for processing as if it was a completely new request, since you are doing a redirect. HOWEVER, now on the 2nd time through you've got the modified URL because the rewrite was processed before doing the hand-off.
In other words [L] does the mangling, then says "OK, we are done here, drop out to normal web processing now".
[L,R=301] does the mangling, then says "we are done with THAT, now got tell whomever is next is line that we've done a redirect".
That last part of the [L,R=301] triggers a whole new set of logic to process the "hey, we just got a redirect" rules. In your case, causing the entire rewrite sequence to be processed from the top with the mangled URL this time around.

URL Rewriting invisibly - How to prevent rewritten URL to appear in the address bar?

I have browsed the other topics, including this one: Mod_rewrite invisibly: works when target is a file, not when it's a directory, but I can't find a solution to my problem.
I have the following rewriting rule:
RewriteRule ^([a-zA-Z0-9_-]+)$ ./index.php?s=$1 [L,NC]
RewriteRule ^([a-zA-Z0-9_-]+)/$ ./index.php?s=$1 [L,NC]
What it does is to write anything like http://myaddress/parameter to http://myaddress/index.php?s=parameter and show this new rewritten address in the browser's address bar.
How can I make rewriting without showing the rewritten URL in the address bar?
Edit
This is the content of my .htaccess file:
DirectoryIndex index.php
RewriteEngine On
RewriteRule ^([a-z0-9_\-]+)/?$ index.php?s=$1 [L,NC,QSA]
RewriteRule ^([a-zA-Z0-9_-]+)\/?([a-zA-Z0-9_-]+)\/?$ index.php?u=$1&s=$2 [L,NC]
RewriteRule ^([a-zA-Z0-9_-]+)\/?([a-zA-Z0-9_-]+)\/?([a-zA-Z0-9_-]+)\/?$ index.php?u1=$1&u2=$2&s=$3 [L,NC]
1. No need for 2 rules that do the same job (the only difference is presence of trailing slash).
2. No need to have a-zA-Z in pattern if you have [NC] flag -- a-z is enough.
3. Try rule without ./
Considering all the above mentioned the rule will become:
RewriteRule ^([a-z0-9_\-]+)/?$ index.php?s=$1 [L,NC,QSA]
P.S.
I have also added the QSA flag to preserve original query string (if present).
The rule is tested and is working fine. If it still does not work for you then post ALL rewrite rules that you have.
This should work:
RewriteEngine On
RewriteRule ^([-a-zA-Z0-9_]+)$ index.php?s=$1 [L]
RewriteRule ^/?$ index.php [L]

mod_rewrite: How to match file in directory or in root depending on 'availability'?

Hello, long time listener, first time caller here!
Thank you for the excellent advice you all share.
I have these mod_rewrite rules set up:
RewriteRule ^([^/.]+)/([^/.]+)/?$ $1--$2.php?%{QUERY_STRING} [L]
RewriteRule ^([^/.]+)/?$ $1.php?%{QUERY_STRING} [L]
They make /company/services/ redirect to company--services.php. Or /company/ to company.php. Works perfect.
But now I'd like to another rule that if I were to put services.php inside physical directory /company/ it will match and redirect that. And if failing that, look for my initial rule. (And failing that, return 404.)
I figured it would be as simple as including:
RewriteRule ^([^/.]+)/([^/.]+)/?$ $1/$2.php?%{QUERY_STRING} [L]
but not so. It will returns a 404 instead. I'm a bit stumped as this goes against how I believed mod_rewrite to work (if a rule does not match, go to the next one.)
Thank you for any pointers!
Found it. For reference, this is the complete set of rules:
RewriteCond %{DOCUMENT_ROOT}/$1/$2.php -f
RewriteRule ^([^/.]+)/([^/.]+)/?$ /$1/$2.php?%{QUERY_STRING} [L]
RewriteRule ^([^/.]+)/([^/.]+)/?$ $1--$2.php?%{QUERY_STRING} [L]
RewriteRule ^([^/.]+)/?$ $1.php?%{QUERY_STRING} [L]

mod rewrite and static pages

is possible to exclude a url being parsed by mod rewrite?
my .htaccess has rewrite rules like
RewriteRule ^contact contact_us.php
and a couple more static pages.
currently my site don't have troubles cause uses http://domain.com/user.php?user=username
but now i need rewrite to:
http://domain.com/username
I've tried with:
RewriteRule ^(.*)$ user.php?user=$1 [L]
but all my site stops working...
is possible to avoid parse my static pages like contact/feed/etc being treated like usernames?
edit to match david req:
this is my actual .htaccess file:
RewriteEngine On
Options +Followsymlinks
RewriteRule ^contact contact_us.php [L]
RewriteRule ^terms terms_of_use.php [L]
RewriteRule ^register register.php [L]
RewriteRule ^login login.php [L]
RewriteRule ^logout logout.php [L]
RewriteRule ^posts/(.*)/(.*) viewupdates.php?username=$1&page=$2
RewriteRule ^post(.*)/([0-9]*)$ viewupdate.php?title=$1&id=$2
RewriteRule ^(.*)$ profile.php?username=$1 [L]
also i've enabled modrewrite log my first file:http://pastie.org/1044881
Put the rewrite rules for the static pages first, and add the [L] flag to them:
RewriteRule ^contact contact_us.php [L]
...
then after those, use your rewrite rule for the username:
RewriteRule ^(.*)$ user.php?user=$1 [L]
(hopefully nobody has a username of contact).
EDIT: Based on the log output you posted (which I'm assuming corresponds to an unsuccessful attempt to access the contact page... right?), try changing the contact rewrite rule to either
RewriteRule ^contact$ contact_us.php [L]
or
RewriteRule ^contact contact_us.php [L,NS]
That is, either add $ to make the pattern match only the literal URL contact, or add the NS flag to keep it from applying to subrequests. According to the log output, what seems to have happened is that Apache rewrites contact to contact_us.php and then does an internal subrequest for that new URL. So far so good. The weird thing is that the ^contact pattern again matches contact_us.php, "transforming" it to contact_us.php, i.e. the same thing, which Apache interprets as a signal that it should ignore the rule entirely. Now, I would think Apache would have the sense to ignore the rule only on the subrequest, but I'm not sure if it's ignoring the entire rewriting process and leaving the original URL, /contact, as is. If that's the case, making one of the changes I suggested should fix it.
EDIT 2: your rewrite log excerpt reminded me of something: I'd suggest making the rewrite rule
RewriteRule ^([^/]+)$ user.php?user=$1 [L]
since slashes shouldn't be occurring in any usernames. (Right?) Or you could do
RewriteRule ^(\w+)$ user.php?user=$1 [L]
if usernames can only include word characters (letters, numbers, and underscore). Basically, make a regular expression that matches only any sequence of characters that could be a valid username, but doesn't match URLs of images or CSS/JS files.
The -f and -d options to RewriteCond check if the current match is a file or directory on disk.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ....

mod_rewrite - redirect from one domain to another and preserve trailing values in url

I think this is a pretty straight forward question in mod_rewrite:
I got one domain, which needs to redirect to another, but keep any value after last slash (/) in the first URL, over to the second.
domain.com/4433 should transfer to domain.com/folder/?p=4333
Listed for clarity:
From: domain.com/4433
To: domain.com/folder/?p=4333
Any ideas?
Edit:
Did some testing, we found the following solution:
RewriteCond %{HTTP_HOST} ^domain.com$
RewriteRule ^([0-9a-z]*)$ /folder/?p=$1 [NC]
sincerely,
- bakkelun
In case you don't really want to redirect but to have pretty URLs, you can use
RewriteEngine On
RewriteRule ^/(.+)$ /folder?p=$1 [L]
This takes everything after the first slash and inserts it at the $1 - but only if there's something after the slash. It doesn't issue a redirect so the users won't notice.
Without any further information, try this:
RewriteEngine on
RewriteRule ^/([^/]+)$ /folder/?p=$1
If you want to use the rule in a .htaccess file, remove the leading slashes.
RewriteEngine On
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^(.*)$ domain.com/folder?p=$1 [R=301,L]
Just in case: domain.com = domain1.com and domain2.com? domain1.com should be redirected to domain2.com? Both run on the same server (optional)?
[EDIT:]
If you really only want to do the thing as stated in the comment, then do the following:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^domain1.com$
RewriteRule ^4433$ http://domain2.com/folder/?p=4433 [R=301,L]
Else, as Benedikt Eger said, or with R=301 if you want real redirection.
Or, if you want it to redirect only on numbers, then do the following:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^domain1.com$
RewriteRule ^([0-9])+$ http://domain2.com/folder/?p=$1 [R=301,L]
RewriteCond checks, if defined vhost is domain1.com, but not domain2.com, then the rewrite rule is applied, and redirects via HTTP status 301 [R=301] only number strings (0-9)+ consisting of at least one number to the specified URL. [L] makes this the last rule applied.

Resources