503 htaccess file only partially working - linux

Using the following as a 503 forwarder on a wordpress website. For some reason it words for foo.com/xyz, but not foo.com itself. Any thoughts?
.htaccess file:
ErrorDocument 503 /rdi/index.php
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* /rdi/index.php [R=503,L]

Any url that ends with a / requests a folder, and any url that does not end on a / requests a file. When you request http://example.com, you actually request http://example.com/, the document root of example.com. Your document root is obviously an existing folder, since otherwise you wouldn't be able to run a site at all.
You are using the following rule:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* /rdi/index.php [R=503,L]
The second condition says: "If the requested filename is not a directory". Your document root is a directory, so that condition is false. It won't rewrite.
You can use the following rule:
RewriteCond %{REQUEST_URI} ^/$ [OR]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* /rdi/index.php [R=503,L]
What will this do? If you request http://example.com, the first condition will match, the second will be ignored because of the [OR] flag, and the third condition will be true. If you request http://example.com/rdi/, the first condition will be false and the second condition will be false and so the rule will not be used. If you request http://example.com/asdfasdf/, the first condition will be false, but due to the [OR] flag it will try the second condition, which is true. Then it checks the third condition which is true, which will then rewrite the request.

Related

htaccess Rewrite rule not working as I expected

I have the following rule:
RewriteRule ^(.*)$ index.php?ip=$1 [L]
But it's not working, instead it is loading:
https://example.com/?ip=index.php
Am I missing something?
Your rule is looping because there is no condition to stop rewriting for existing files and directories.
After first rewrite it becomes:
index.php?id=1.2.3.4
and after second rewrite URI becomes:
index.php?id=index.php
You can use this rule to fix this behavior:
# If the request is not for a valid directory
RewriteCond %{REQUEST_FILENAME} !-d
# If the request is not for a valid file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?ip=$1 [L,QSA]

How can I instruct Apache to apply different URL rewriting rules based on a query variable in the requested URL?

I have a set of rules in a .htaccess file that redirects all requests to index.php, but this is interfering with AJAX requests that need to access the requested file directly.
I am trying to resolve this by appending ?ajax=true to all AJAX request URLs, and creating a rule that says "all URLs ending in ?ajax=true should be processed directly".
Here is my .htaccess file currently:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{QUERY_STRING} !^ajax=true$
RewriteRule ^(.*)$ index.php?params=$1 [NC]
My AJAX request URL would be as follows:
http://www.example.com/process_ajax.php?ajax=true
No luck so far.
I think you are close with using a negative RewriteCond but the syntax could be a bit off. Try using parentheses like in my example below.
At first, I would use a wildcard value for the GET parameter like .* so you can focus on targeting the correct key. Once it's working you can test again for getting the right value, presumably true.
Try:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{QUERY_STRING} !(ajax=.*)$
RewriteRule ^(.*)$ index.php?params=$1 [NC]

.htaccess rules to separate page types

I'm having some problems rewriting URLs with the following rules
RewriteEngine on
RewriteRule ^page/(.*)$ index.php?pag=cms&title=$1 [NC]
RewriteRule ^admin/(.*)$ admin/$1 [NC]
RewriteRule ^(.*)$ index.php?pag=$1 [NC,L]
What I'm trying to achieve is to check if the URL is a cms page or not and leave admin URLs as they are.
If I remove the last condition it works but I will have no rule for not cms pages.
Ideally I would want to have just one rule for every page (cms or not) but I can't figure out how to check that other than using page/ in the URL.
Mod_rewrite will keep looping through all the rules until the URI stops changing (or it reaches its internal redirect limit, resuling in a 500 error). You need to add a few conditions to the last rule so that it won't rewrite URI's that's already been properly routed:
RewriteRule ^page/(.*)$ index.php?pag=cms&title=$1 [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?pag=$1 [NC,L]
Additionally, the second rule does nothing except a passthrough, so you can replace it with
RewriteRule ^admin/(.*)$ - [NC,L]
You need these rules:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
From the Apache documentation:
'-d' (is directory)
Treats the TestString as a pathname and tests whether or not it exists, and is a directory.
'-f' (is regular file)
Treats the TestString as a pathname and tests whether or not it exists, and is a regular file.

How to rewrite to a script and also redirect away from that script using .htaccess while avoiding infinite loops

I want to have all the URLs on my site handled by a single script. So I put in a rewrite rule like this:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) /myscript.php?p=$1 [L]
But I don't want to allow access to my script on URLs that actually contain "myscript.php" in them so I would like to redirect those back to the main site:
Redirect 301 /myscript.php http://example.com/
The problem is that if I put both of those rules into my .htaccess file it causes an infinite loop. How do I get them both to work at the same time?
I would also like to be able to redirect things like:
/myscript.php?p=foo -> /foo
You can set an environment variable
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !myscript\.php
RewriteRule (.*) /myscript.php?p=$1 [L,E=LOOP:1]
and test for that in your second rule
RewriteCond %{ENV:REDIRECT_LOOP} !1
RewriteRule ^myscript\.php$ / [R,L]
Never test with 301 enabled, see this answer Tips for debugging .htaccess rewrite rules for details.
Using an environment variable is perfectly OK, however, you don't need to manually set this environment variable yourself. Apache provides the REDIRECT_STATUS environment variable which can be used for this purpose.
REDIRECT_STATUS is empty (or not set) on the initial request. It is set to 200 on the first (successful) internal rewrite. Or some other HTTP status code in the case of an error (404 etc.).
So, instead of checking that REDIRECT_LOOP is not 1, we can simply check that REDIRECT_STATUS is empty to ensure we are testing the initial request and not the rewritten request. For example:
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^myscript\.php$ / [R,L]
(Note that it is just REDIRECT_STATUS, there is no STATUS variable at the start of the request.)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !myscript\.php
RewriteRule (.*) /test/myscript.php?p=$1 [L,E=LOOP:1]
Aside: The RewriteCond directive that checks against the REQUEST_URI doesn't really do anything here. If the first condition is true (ie. it's not a file), then this condition must also be true. However, it could be optimised by including this condition first. This would then avoid the file check on every request (including the rewritten request). For example:
RewriteCond %{REQUEST_URI} !^/test/myscript\.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) /test/myscript.php?p=$1 [L]
Or, you could include a pre-check (an exception) before this rule instead that halts processing when myscript.php is requested:
RewriteRule ^test/myscript\.php$ - [L]
However, if you do this, then the above canonical redirects must appear before these rules, otherwise they will never be processed. (Putting the canonical redirects first is generally preferable anyway.)

mod_rewrite with .htaccess to spoof subdirectory

I have a django app running on a subdomain, subdomain.domain.com/appname, but I don't want the app name to show up in any of my urls. I have accomplished this via .htaccess
RewriteEngine On
RewriteCond %{REQUEST_URI} !admin
RewriteCond %{REQUEST_URI} !appname
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /appname/$1 [L]
This accompishes the case where the requested url is subdomain.domain.com/home and it is served from subdomain.domain.com/appname/home.
However, I'd also like to accomplish the reverse, where the requested url is subdomain.domain.com/appname/home, and the displayed url changes to subdomain.domain.com/home, which then triggers the rule above and is served from subdomain.domain.com/appname/home
I tried the following but got an error that I have a loop
RewriteEngine On
RewriteCond %{REQUEST_URI} appname
RewriteRule ^appname/(.*)$ /$1 [N,R=301]
RewriteCond %{REQUEST_URI} !admin
RewriteCond %{REQUEST_URI} !appname
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /appname/$1 [L]
Try without the 'N' flag:
'next|N' (next round)
Re-run the rewriting process (starting again with the first rewriting rule). This time, the URL to match is no longer the original URL, but rather the URL returned by the last rewriting rule. This corresponds to the Perl next command or the continue command in C. Use this flag to restart the rewriting process - to immediately go to the top of the loop.
Be careful not to create an infinite loop!
http://httpd.apache.org/docs/current/mod/mod_rewrite.html

Resources