18

I have a simple .htaccess file with the contents below.

<IfModule mod_rewrite.c>
     RewriteEngine on

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

     RewriteRule ^(.*)$ index.php?s=$1 [L]
</IfModule>

I want to add this rule.

RewriteRule ^p$ index.php?p=

I tried doing this below but it doesn't work. It seems like both rules are being run. I have tried a couple of different flags and again have had no luck. Could someone tell me how to get this working please.

<IfModule mod_rewrite.c>
     RewriteEngine on

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

     RewriteRule ^p$ index.php?p=
     RewriteRule ^(.*)$ index.php?s=$1 [L]
</IfModule>
1

3 Answers 3

55

You must add [L] flag to stop reading rules when one match:

<IfModule mod_rewrite.c>
     RewriteEngine on

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

     RewriteRule ^p$ index.php?p= [L]
     RewriteRule ^(.*)$ index.php?s=$1 [L]
</IfModule>

Reminder of RewriteRule flags:

Flag Name Description
L Last Stop processing RewriteRules once this one matches. Order matters!
C Chain Continue processing the next RewriteRule. If this rule doesn't match, then the next rule won't be executed. More on this later.
E Set environmental variable Apache has various environmental variables that can affect web-server behavior.
F Forbidden Returns a 403-Forbidden error if this rule matches.
G Gone Returns a 410-Gone error if this rule matches.
H Handler Forces the request to be handled as if it were the specified MIME-type.
N Next Forces the rule to start over again and re-match. BE CAREFUL! Loops can result.
NC No case Allows [jpg] to match both jpg and JPG.
NE No escape Prevents the rewriting of special characters (. ? # & etc) into their hex-code equivalents.
NS No subrequests If you're using server-side-includes, this will prevent matches to the included files.
P Proxy Forces the rule to be handled by mod_proxy. Transparently provide content from other servers, because your web-server fetches it and re-serves it. This is a dangerous flag, as a poorly written one will turn your web-server into an open-proxy and That is Bad.
PT Pass Through Take into account Alias statements in RewriteRule matching.
QSA QSAppend When the original string contains a query (http://example.com/thing?asp=foo) append the original query string to the rewritten string. Normally it would be discarded. Important for dynamic content.
R Redirect Provide an HTTP redirect to the specified URL. Can also provide exact redirect code [R=303]. Very similar to RedirectMatch, which is faster and should be used when possible.
S Skip Skip this rule.
T Type Specify the mime-type of the returned content. Very similar to the AddType directive.

It is an extract from this (very) complete post: Redirect, change URLs or redirect HTTP to HTTPS in Apache - Everything you ever wanted to know about mod_rewrite rules, but were afraid to ask

Sign up to request clarification or add additional context in comments.

2 Comments

The code posted here is wrong. By "shoehorning" this second rule in the middle of the existing rule, you are breaking the existing rule. The second RewriteRule is now processed unconditionally which breaks the front-controller pattern.
RewriteCond is valid for both rules, I don't see any "unconditional" processing. Please provide more details in your statement.
14

You should know first that the rewrite conditions only affect the following rewrite rule, and you added your new rule between the rewrite conditions and the rewrite rule. That means they will now affect your new rule only and not the old one (what you have in you code is that the rewrite rules are only executed if the targeted URL is not a file or a directory). If you want your old rule to be still affected by the rewrite condition, you will have to add your new rule before the rewrite conditions.

For your issue, I think zessx has answered enough (it is fixed by adding the [L] flag).

In the end, you should have something like this:

<IfModule mod_rewrite.c>
     RewriteEngine on

     RewriteRule ^p$ index.php?p= [L]

     RewriteCond %{REQUEST_FILENAME} !-f
     RewriteCond %{REQUEST_FILENAME} !-d
     RewriteRule ^(.*)$ index.php?s=$1 [L]
</IfModule>

Comments

0

Just as a heads-up for future devonauts: keep in mind that Apache has a built-in directive to not allow encoded slashes (%2F) in the URL when using rewrite; it took me a while to figure that one out...

Adding AllowEncodedSlashes NoDecode made everything work again since I had encoded slashes in the URL. It doesn't work in a Directory context / .htaccess though...

The documentation about the B rewrite flag hints at this.

AllowEncodedSlashes directive documentation.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.