I'm not quite sure why this isn't working, but I keep getting either 404s or 500s. I'm trying to redirect subdirectories to the root directory with a query string tacked on. So if I go to example.com/dir, I will be redirected (behind the scenes, obviously) to example.com/?url=dir. I tried using this, but it doesn't seem to work:
RewriteEngine On
RewriteRule [^?](.+) ?page=$1 [L,QSA,NC]
I thought it would get anything after the domain name that doesn't start with a query string (to prevent infinite redirect loops), and send it to the homepage with a query string tacked on. But it isn't working. How can I do this?
RewriteRule [^?](.+) ?page=$1 [L,QSA,NC]
The RewriteRule pattern matches against the URL-path only. This never contains the query string (which is available in a separate server variable: QUERY_STRING).
You should also rewrite to the actual file that is handling the request. If you simply rewrite to ?page=$1 then you are relying on mod_dir to make an additional subrequest for the index document. If the index document is index.php then rewrite directly to that, ie. index.php?page=$1.
The above looks like it will result in a rewrite loop.
Try the following instead:
RewriteCond %{QUERY_STRING} !^page=
RewriteRule (.+) index.php?page=$1 [NS,L,QSA]
The preceding condition checks that the query string does not start with "page=".
The NC is not required here, since you are simply capturing everything, regardless of case.
The NS (nosubrequest) flag prevents the rule being called when mod_dir issues a subrequest for the directory index. In other words, it prevents a request for example.com/ being internally rewritten to index.php?page=index.php.
Related
Have been trying to write a redirect rule with query string but did not succeed.
I have the URL example.com/blog/?page=1 or example.com/blog/?hello, so it does not really matter what goes in the query string. How do I write a Redirect rule, so that it cuts the query string and redirects to the URL before the query string. For example, both of those URLs have to redirect to example.com/blog/ so that URL does not contain any query string.
I was trying
RewriteRule ^blog/?$ blog/ [R=301,L,NE] but got redirected to 404 page.
Also tried
RewriteRule ^blog/?$ /blog/ [R=301,L,NE] and got the message that page is not working, 'URL' redirected you too many times.
BTW, technology I am using is Gatsby with htaccess plugin.
To remove the query string you first need to check that there is a query string to remove, otherwise, it should do nothing.
For example, to remove the query string from /blog/?<query-string> you would do something like this:
RewriteCond %{QUERY_STRING} .
RewriteRule ^(blog)/?$ /$1/ [QSD,R=302,L]
This matches the URL-path blog/ (trailing slash optional) and redirects to /blog/ (with a trailing slash). Your example URL includes the trailing slash, but your regex appears to suggest the trailing slash is optional?
The preceding condition (RewriteCond directive) checks the QUERY_STRING server variable to make sure this is non-empty (ie. it matches a single character, denoted by the dot).
The $1 backreference in the substitution string contains the value from the captured group in the preceding RewriteRule pattern. ie. "blog" in this example. This simply saves repetition. You could just as easily write RewriteRule ^blog/?$ /blog/ [QSD,R,L] instead.
The QSD (Query String Discard) flag removes the original query string from the redirected response, otherwise, this would be passed through by default (which would create a redirect-loop).
If the request does not contain a query string then this rule does nothing (since the condition will fail).
If this is intended to be permanent then change the 302 (temporary) redirect to 301 (permanent), but only once you have confirmed this works as intended. 301s are cached persistently by the browser so can make testing problematic.
A look at your existing rules:
was trying RewriteRule ^blog/?$ blog/ [R=301,L,NE] but got redirected to 404 page.
By default, the relative substitution string (ie. blog/) is seen as relative to the directory that contains the .htaccess file and this "directory-prefix" is then prefixed back to the relative URL, so this will (by default) result in a malformed redirect of the form https://example.com/path/to/public_html/blog/.
Also tried RewriteRule ^blog/?$ /blog/ [R=301,L,NE] and got message that page is not working, 'url' redirected you too many times.
This is not checking for (or removing) the query string so this is basically just redirecting to itself - an endless redirect-loop.
Remove any query string from any URL
What rule do i write, to remove query string from any URL.
Modify the RewriteRule pattern to match any URL and redirect to the same. For example:
RewriteCond %{QUERY_STRING} .
RewriteRule (.*) /$1 [QSD,R=302,L]
This needs to go at the top of the root .htaccess file before any existing rewrites.
If the .htaccess file is in a subdirectory (not the root) then you will need to do something like the following instead, since the $1 backreference (as used above) won't contain the complete root-relative URL-path.
RewriteCond %{QUERY_STRING} .
RewriteRule ^ %{REQUEST_URI} [QSD,R=302,L]
Have been trying to write a redirect rule with query string but did not succeed.
I have the URL example.com/blog/?page=1 or example.com/blog/?hello, so it does not really matter what goes in the query string. How do I write a Redirect rule, so that it cuts the query string and redirects to the URL before the query string. For example, both of those URLs have to redirect to example.com/blog/ so that URL does not contain any query string.
I was trying
RewriteRule ^blog/?$ blog/ [R=301,L,NE] but got redirected to 404 page.
Also tried
RewriteRule ^blog/?$ /blog/ [R=301,L,NE] and got the message that page is not working, 'URL' redirected you too many times.
BTW, technology I am using is Gatsby with htaccess plugin.
To remove the query string you first need to check that there is a query string to remove, otherwise, it should do nothing.
For example, to remove the query string from /blog/?<query-string> you would do something like this:
RewriteCond %{QUERY_STRING} .
RewriteRule ^(blog)/?$ /$1/ [QSD,R=302,L]
This matches the URL-path blog/ (trailing slash optional) and redirects to /blog/ (with a trailing slash). Your example URL includes the trailing slash, but your regex appears to suggest the trailing slash is optional?
The preceding condition (RewriteCond directive) checks the QUERY_STRING server variable to make sure this is non-empty (ie. it matches a single character, denoted by the dot).
The $1 backreference in the substitution string contains the value from the captured group in the preceding RewriteRule pattern. ie. "blog" in this example. This simply saves repetition. You could just as easily write RewriteRule ^blog/?$ /blog/ [QSD,R,L] instead.
The QSD (Query String Discard) flag removes the original query string from the redirected response, otherwise, this would be passed through by default (which would create a redirect-loop).
If the request does not contain a query string then this rule does nothing (since the condition will fail).
If this is intended to be permanent then change the 302 (temporary) redirect to 301 (permanent), but only once you have confirmed this works as intended. 301s are cached persistently by the browser so can make testing problematic.
A look at your existing rules:
was trying RewriteRule ^blog/?$ blog/ [R=301,L,NE] but got redirected to 404 page.
By default, the relative substitution string (ie. blog/) is seen as relative to the directory that contains the .htaccess file and this "directory-prefix" is then prefixed back to the relative URL, so this will (by default) result in a malformed redirect of the form https://example.com/path/to/public_html/blog/.
Also tried RewriteRule ^blog/?$ /blog/ [R=301,L,NE] and got message that page is not working, 'url' redirected you too many times.
This is not checking for (or removing) the query string so this is basically just redirecting to itself - an endless redirect-loop.
Remove any query string from any URL
What rule do i write, to remove query string from any URL.
Modify the RewriteRule pattern to match any URL and redirect to the same. For example:
RewriteCond %{QUERY_STRING} .
RewriteRule (.*) /$1 [QSD,R=302,L]
This needs to go at the top of the root .htaccess file before any existing rewrites.
If the .htaccess file is in a subdirectory (not the root) then you will need to do something like the following instead, since the $1 backreference (as used above) won't contain the complete root-relative URL-path.
RewriteCond %{QUERY_STRING} .
RewriteRule ^ %{REQUEST_URI} [QSD,R=302,L]
I'm trying to block access to our /admin.php page and anything related to admin.php (this isn't a folder in our file system, we're using a central .htaccess in root).
I'm able to do this with the following:
RewriteCond %{REMOTE_ADDR} !^123\.123\.123\.123$
RewriteCond %{THE_REQUEST} ^(.*)?admin\.php(.*)$ [NC]
RewriteRule ^(.*)$ https://oursite.com/$1 [R=301,L]
This works, however, anything after /admin.php sticks in the URL after redirection and goes to 404 page. I just want it to redirect to home.
For example, this URL https://example.com/admin.php?/cp/login&return= redirects to https://example.com/?/cp/login&return=.
It just strips the admin part. I need it to strip everything.
RewriteRule ^(.*)$ https://oursite.com/$1 [R=301,L]
This line would redirect back to itself - it wouldn't "strip the admin part"?! The $1 backreference in the substitution would hold the value admin.php in your example (captured from the (.*) in the RewriteRule pattern). To redirect to the home page you would need to remove the $1 backreference.
The remaining part of the URL in your example (which is everything after the ?) is the query string. By default this is indeed passed on to the substitution (target URL) unaltered. You need the QSD (Query String Discard) flag on Apache 2.4+. Or append a ? on to the end of the substitution string in Apache 2.2 (effectively creating an empty query string).
You also don't need the condition that chacks against THE_REQUEST server variable, as this can be done (more efficiently) in the RewriteRule pattern. (I assume you are not internally rewriting to admin.php?)
So, bringing this together we have:
RewriteCond %{REMOTE_ADDR} !^123\.123\.123\.123$
RewriteRule admin\.php / [QSD,R=302,L]
This checks for "admin.php" occurring anywhere in the URL-path of the requested URL.
You don't need to explicitly state an absolute URL in the substitution if you are redirecting back to the same host.
Note that this is a 302 (temporary) redirect. Only change to a 301 (permanent) - if that is the intention - when you have confirmed it is working OK. 301s are cached hard by the browser so can make testing problematic.
You will need to clear your browser cache before testing.
I have a situation where I want to actually see the url variable even though the rest of my htaccess site uses readable URLS.
The issue is that it is simply showing up as a page not found...
This works...
RewriteRule ^files/(.+)/from_all_files/$ pages/file.php?slug=$1&from=all-files
This does not work
RewriteRule ^files/(.+)?from=all-files$ pages/file.php?slug=$1&from=all-files
Im looking for the second one to work.
You cannot check the query string in a RewriteRule, which can only see the REQUEST_URI. You need to use the following instead:
RewriteCond %{QUERY_STRING} ^from=all-files$ [NC]
RewriteRule ^files/(.+)$ pages/file.php?slug=$1 [QSA,L]
When you request http://example.com/files/some-file?from=all-files, the request will be internally rewritten to pages/file.php?slug=some-file&from=all-files. The Query String Append flag (QSA) will append the current query string to the one you're rewriting to.
So I have some particular variables that mess up the content management system I'm using.
While I debug the code, I'd like to redirect requests with these particular variables back to the index page, but without any query string.
Here's my rule:
RewriteCond %{QUERY_STRING} option\=com\_aicontactsafe\&sTask\=captcha
RewriteRule (.*) "/index.php" [R=301, L]
At this point it is simply writing the file path to index.php after the HTTP_HOST.
This gives a 403, but is not quite what I wanted.
Redirect to /index.php? instead of just /index.php. Normally mod_rewrite doesn't touch the query string, unless you give it a new query string to replace the old one with.