Forum Moderators: phranque

Message Too Old, No Replies

Make htaccess ignore wordpress folders and directories

         

wizz

6:16 pm on Apr 3, 2012 (gmt 0)

10+ Year Member



Hi,

I have a wordpress site where when a person arrives at domain.com/variable I am using htaccess to rewrite the url to become domain.com/?ref=variable

This works fine except that when a page exists that also gets rewritten unless followed with a forward slash / so for example, I have a page called /members and if you went to

domain.com/members that would be rewritten to domain.com/?ref=members which is NOT what I want.

If you go to domain.com/members/ (with the forward slash at the end) then the rewrite does not happen which is what I do want to happen

Is there any way that I can stop the rewrite happening when a person goes to domain.com/members (without the forward slash?)

This is what I have...

RewriteEngine On
RewriteRule ^([0-9a-zA-Z-_]+)$ index.php/?ref=$1 [R,L]

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# END WordPress
Thanks in advance

Steve

lucy24

8:28 pm on Apr 3, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



when a person arrives at domain.com/variable I am using htaccess to rewrite the url to become domain.com/?ref=variable

Your Rewrites are a bit garbled. Before you start...

#1 get rid of the <IfModule... envelope. Not its contents, just the <If and </If lines. They are standard CMS boilerplate, but now that you are in your own htaccess you don't need them. You either have mod_rewrite or-- horrible to contemplate-- you don't.

#2 the line "RewriteEngine On" only needs to occur once per htaccess, before the first Rewrite.

#3 RewriteBase / will do no harm but is rarely necessary, especially in htaccess. / is the default.

#4 Leave a blank line after each RewriteRule so you can see where one starts and another one ends. #annotate the Rules so you will remember what they are supposed to do.

In the (I assume) boilerplate part of your .htaccess, there are two Rules:

If request is for index.php, stop rewriting and proceed to next module.

If request is for anything else, and the "anything else" doesn't really exist (the !-f and !-d lines), then serve content from index.php, keeping the existing query string if any.

Both of these rules collide with (assuming again) your added rule:

RewriteRule ^([0-9a-zA-Z-_]+)$ index.php/?ref=$1 [R,L]

This Rule-- which comes before the other two-- takes any incoming single-word extensionless request, captures it, and 302 redirects to the directory index.php/ replacing the old query string, if any, with the name of the requested file.

Even setting aside the existing-files problem, this is exactly the opposite of what you want to do. Do a quick search in this Forum for the pair of words Rewrite and Redirect. There's a bit of recent boilerplate which I'm pretty sure corresponds to what you're trying to do.

Narrower answer: the difference between /members and /members/ --assuming that's a real directory-- is that one version has met mod_dir (or was correctly entered in the first place) and one hasn't. That's what the !-d line is for, but in real life the Cond should be more exactly coded.

No, I don't know why every single question I've seen in the past 24 hours seems to involve directory-slash redirects at some point.

g1smd

10:32 pm on Apr 3, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I've been having deja vu over and over again for the last 48 hours. :)

I am using htaccess to rewrite the url to become domain.com/?ref=variable

No. That's not at all what you have done.

You have used htaccess to rewrite the URL request to fetch content from the server filepath at
/index.php?ref=variable
in the server filesystem.

A rewrite maps a URL request "out there" on the web to a filepath "here" inside the server, not to a URL.

lucy24

1:16 am on Apr 4, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



You have used htaccess to rewrite the URL request to fetch content from...

You may have overlooked the [R] flag in the first of the three Rules. The other two-- the ones inside the envelope-- are fetch-content-from rewrites.

g1smd

7:01 am on Apr 4, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I did miss it.

The [R] makes it a 302 redirect, so there's a further disconnect from the description of what the user wants it to do and what it actually does.

wizz

8:13 am on Apr 4, 2012 (gmt 0)

10+ Year Member



Thanks for your answers, I have searched redirect rewrite in the forum and have a greater understanding of the difference now but I'm still no nearer fixing what I need. It occurs to me that my explanation may not have been as precise as it might have been. This is what happens

A person arrives at domain.com/variable

/variable does not exist I rewrite it as /?ref=variable using ref= to create a cookie of variable

The only reason I do this is so that people can use domain.com/variable instead of domain.com/?ref=variable (its easier to remember)

This all works fine (rightly or wrongly)

As its wordpress the rest of the htaccess is boilerplate and I probably don't need any of it but need some different htaccess code which is what I can't figure out.

Naturally in wordpress directories don't really exist in a physical way and yet the boilerplate has a rewrite condition for them

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d


It seems to me that what I need is something along the lines of

If /variable exists as a -f or -d 'GO THERE' otherwise do this...

RewriteRule ^([0-9a-zA-Z-_]+)$ index.php/?ref=$1 [R,L]

I'm new to htaccess so apologies in advance if I am being a complete idiot here.

Thanks in advance for any help you may be able to offer.

Steve

lucy24

9:58 am on Apr 4, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Naturally in wordpress directories don't really exist in a physical way

There can still be directories, they just don't have anything to do with what the user sees in their address bar.

Say you've got a corner of your site that's just for your friends. It lives at

www.example.com/secret/deepsecret/deepestdarkestsecretofall.html

When they come along and request the page, you have to ensure that the request doesn't get grabbed by wp and treated like a pseudo-directory: "Well, obviously what they really want is /index.php?secret&secretly&deepsecret"

And that's exactly what the !-f and !-d lines are for. But they are time-consuming lines-- especially if the boilerplate is made to check them for every css or image request it meets. At a minimum, you can tweak it so the Rule only executes when it gets an extensionlesless request. In fact that's what your own Rule does: it excludes all subdirectories (no slash / in the group) and all extensions (no period . in the group).

If you only have a few "real" files or directories, it may be easier on the server just to name them in a Condition:

!(realfile|realplace|ImNotKidding)

wizz

1:55 pm on Apr 4, 2012 (gmt 0)

10+ Year Member



Thanks again for your feedback.

I've just spent several more hours on this and in reality still no nearer a solution that does what I originally hoped could be done. Naturally I don't need to become a htaccess expert so I guess I'm just wasting my time and yours.

The closest I can get (that works) is this

RewriteEngine On
RewriteCond %{REQUEST_URI} !^/(leaders|confirm|presentation)$
RewriteRule ^([0-9a-zA-Z-_]+)$ index.php/?ref=$1 [R,L]


# BEGIN WordPress
<IfModule mod_rewrite.c>
# RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
# RewriteCond %{REQUEST_FILENAME} !-f
# RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# END WordPress

If I remove any of the other boilerplate items it doesn't work at all. For example is I code out RewriteBase / then I get 404 error

Very Frustrating:-(

lucy24

9:18 pm on Apr 4, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



For example if I code out RewriteBase / then I get 404 error

Huh. That's interesting, since / is supposed to be the default. This is shared hosting, right? So who knows what's going on in the config file. The RewriteBase line doesn't do any harm, so just leave it if it makes the server happy :)

Does anything bad happen if you comment-out the two "envelope" lines with IfModule? Again, they don't do any harm except for making the server spend an extra nanosecond checking to see if mod_rewrite is still where it's supposed to be.

Oh, wait. Rewind. Does the RewriteBase have to be in that exact location for all your Rewrites to work? That is, after the first RewriteRule but before the other two? That implies your first Rule is using a different Base-- which is decidedly weird and merits some more looking into.

It still seems as if your RewriteRules are doing the exact opposite of what you want. Was going to say "It must be frustrating" and then saw that you were already there ;)

wizz

9:12 am on Apr 5, 2012 (gmt 0)

10+ Year Member



Hi again,

This is shared hosting on plesk.

I spent so many hours on this I confused myself even more and what I posted was not entirely accurate. A fresh look at this trying a few of your suggestions this morning and I have at least learned a little more.

1. It doesn't matter where the RewriteBase goes as you will see below with my current config.

2. I can code out the IfModules

3. If I remove the Request_Filename conditions it breaks the site formatting to text only

What I cannot understand is why this does not work as this makes sense to me? (but clearly I am no expert)
===============

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([0-9a-zA-Z-_]+)$ index.php/?ref=$1 [R,L]

I interpret the above as Rewrite engine on, if it is NOT a file and Not a directory then change the URL from domain.com/variable to domain.com/?ref=variable

==================
Anyway, this (Below) is what I have now and this works.

========

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} !^/(leaders|confirm|presentation)$
RewriteRule ^([0-9a-zA-Z-_]+)$ index.php/?ref=$1 [R,L]


# BEGIN WordPress
# <IfModule mod_rewrite.c>
# RewriteEngine On
# RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
# </IfModule>

# END WordPress

============
The only downside to this is that every time I create a page in Wordpress I have to add it into the Condition line, which is a real pain.

RewriteCond %{REQUEST_URI} !^/(leaders|confirm|presentation)$

Thanks again for your help, maybe I'm just approaching it all wrong?

Steve

g1smd

10:50 am on Apr 5, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I don't understand why you would want the user to ask for example.com/thispage and then redirect them to example.com/index.php?ref=thispage changing the URL they see in their browser to the one with parameters.

Why don't they just ask for example.com/index.php?ref=thispage in the first place?

Or, did you intend a rewrite instead of a redirect? This is where the user asks for example.com/thispage and the content of /index.php?ref=thispage is returned at the originally requested URL; i.e. the browser address bar remains at example.com/thispage.

wizz

11:22 am on Apr 5, 2012 (gmt 0)

10+ Year Member



Hi,

The ref=variable is used to created a cookie setting the 'variable' into the cookie. The 'variable' is always the persons username.

You are correct that I can tell the user to use example.com/index.php?ref=variable but they don't easily remember that. Much better and more memorable for users who easily remember the URL they need is example.com/variable E.G example.com/steve gets rewrite to example.com/?ref=steve which creates the cookie 'steve'

It's all about making it user friendly.

Steve

g1smd

11:53 am on Apr 5, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



E.G example.com/steve gets rewrite to example.com/?ref=steve which creates the cookie 'steve'

No. There is no rewrite. They are redirected. The URL as shown in the browser address bar changes.

With a rewrite, the URL as shown would not change.

wizz

12:24 pm on Apr 5, 2012 (gmt 0)

10+ Year Member



Yes you are correct. I'm no expert and I misread your previous reply.

So yes, its a redirect rather than a rewrite..

In truth, I don't care what we call it as long as it works..lol

g1smd

12:47 pm on Apr 5, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



It works. But it is not the right solution.

You need a rewrite here, not a redirect.

wizz

2:34 pm on Apr 5, 2012 (gmt 0)

10+ Year Member



@G1smd

I'm looking for help here and telling me its not right is not a lot of help:-(

You have me even more confused now..lol

No offence but instead of typing 'It works but its not the right solution.' Would it not be easier to show me what is the right solution?

Steve

lucy24

6:05 pm on Apr 5, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Would it not be easier to show me what is the right solution?

It would definitely be much faster. This is not a dig at you; it's a general truth. And there are plenty of forums where you can post a question and someone will obligingly spit out the code for you. But this is WebmasterWorld. People do this stuff for their day jobs. It's the "teach a man to fish" principle. Or, if you want a less annoying analogy: It's like telling your kid to clean his room. You can do it yourself in a tenth the time. But the goal is for kid to learn how to do it himself, so that when he grows up he can stand over your grandkids and make them clean their rooms.

And now about those redirects that ought to be rewrites:

[webmasterworld.com...]

This is brand-new boilerplate, so the wording is not yet perfect, but I'm pretty sure there aren't any lethal typos. g1 would have said something. Probably with great inner satisfaction, since I'm becoming quite familiar with his own typos.