I'm working with Apache and want to use .htaccess to achieve the following:
Essentially, I want to allow only these two specific endpoints (/api/get and /api/report), and prevent access to anything else.
What ive tried:
RewriteEngine on
RewriteRule ^api/get$ /get.php [L]
RewriteRule ^api/report$ /report.php [L]
Order deny,allow
Deny from all
<Files "get.php">
Allow from all
</Files>
<Files "report.php">
Allow from all
</Files>
Resulting in access being denied to everything except /get.php and /report.php
RewriteEngine on
RewriteRule ^api/get$ /get.php [L]
RewriteRule ^api/report$ /report.php [L]
RewriteRule ^ - [F]
Leading to complete access denial
You can do it like this on Apache 2.4:
RewriteEngine on
# Rewrite requests to "/api/get" and "/api/report"
RewriteRule ^api/(get|report)$ $1.php [END]
# Block everything else, including direct requests to "/get.php" and "/report.php"
RewriteRule ^ - [F]
Note the use of the END
flag (as opposed to L
) on the first rule (requires Apache 2.4+). This prevents any further rules being processed (for the request) should this rule be met. (An L
flag simply prevents additional rules being processed during the current pass only by the rewrite engine.)
The $1
backreference contains either get
or report
as captured from the initial request URL. This allows your two rules to be easily combined.
No need for the slash-prefix on the RewriteRule
substitution (2nd argument) in the above rule. This ensures we rewrite directly to a file-path, as opposed to a URL-path (although it would get there in the end).
Aside:
RewriteRule ^api/get$ /get.php [L] RewriteRule ^api/report$ /report.php [L] RewriteRule ^ - [F]
This is close, but without an additional condition on the last rule, the use of the L
flag on the first two rules would result in all requests being blocked.
If on Apache 2.2, this could be written like this, making use of the REDIRECT_STATUS
environment variable:
RewriteRule ^api/get$ /get.php [L]
RewriteRule ^api/report$ /report.php [L]
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^ - [F]
The use of the REDIRECT_STATUS
env var ensures that only direct requests (from the client) are processed (ie. blocked) and not rewritten requests by the previous two rules. On the initial pass by the rewrite engine, the REDIRECT_STATUS
var is empty, but after the first successful internal rewrite it is set to 200
(as in a 200 OK HTTP status).
RewriteCond %{REQUEST_URI} !^/api/get$ [OR] RewriteCond %{REQUEST_URI} !^/api/report$ RewriteRule ^ - [F] RewriteRule ^api/get$ get.php [L] RewriteRule ^api/report$ report.php [L]
As mentioned in comments, the logic is incorrect on the first rule. If you OR two negated mutually exclusive expressions the result will always be true and the request is always blocked.
However, the request would still be blocked for the same reason as mentioned above.