At first the rule that works:
DirectoryIndex index.php
ErrorDocument 403 /form.html
RewriteCond %{REQUEST_URI} ^/index\.php$
RewriteCond %{REQUEST_METHOD} !POST
RewriteRule . - [F,L]
This means http://example.com
and http://example.com/index.php
can only be opened through POST
.
Now the problem
I added this additional rule set:
RewriteCond %{REQUEST_URI} !^/index\.php$
RewriteRule . - [F,L]
Now, I send a POST again to http://example.com
but receive this error:
Forbidden
You don't have permission to access / on this server.
Additionally, a 500 Internal Server Error error was encountered while trying to use an ErrorDocument to handle the request.
This does not make sense, because the rule should NOT catch requests on index.php
sending a 403, but ok, I extended the second rule as follows:
RewriteCond %{REQUEST_URI} !^/form\.html$
RewriteCond %{REQUEST_URI} !^/index\.php$
RewriteRule . - [F,L]
And sending again a POST to http://example.com returns no 500, but I still receive a 403?!
Update 1
If I remove the first rule set, the second one works alone as expected. This means only http://example.com
, http://example.com/index.php
and http://example.com/form.html
can be accessed.
Update 2
If I use both rule sets and send my POST to http://example.com/index.php
I do not receive any errors?!
So the rules interfere only if I sent a POST to the root URL. But why?
Assuming your
DirectoryIndex
is set toindex.php
and you have no other directives then it would seem to be your first rule block that is resulting in the 403 Forbidden when accessinghttp://example.com/
. The above only allows direct POST requests to/index.php
.The
RewriteRule
pattern (a single dot) in the above prevents the rule being processed at all for requests tohttp://example.com/
. mod_dir then initiates an internal subrequest to/index.php
. Note that this subrequest actually appears as an internal GET request (which is what theREQUEST_METHOD
server variable gets set to), so the above condition (!POST
) is successful and the request is ultimately forbidden.It would be preferable to canonicalise the request and externally redirect (308 - permanent redirect preserving the request method) any request for
/index.php
to/
. You can then concentrate on matching just/
and can ignore subrequests.(No need for the
L
flag whenF
is used.L
is implied.)Make sure the browser cache is clear before testing. (It might be preferable to test with
R=307
(temporary) redirects to avoid the cache.)As you suggest, this does not conflict with the above rules, it matches anything other than
/
and/index.php
(when used in.htaccess
). So, this forbids access to all other URLs, regardless of the request method. (As mentioned above, it appears to be the first rule that was triggering the 403 when accessinghttp://example.com/
.) Providing you include an exception for your error documents, as above, then you don't need to add an additional condition.