apache SetEnvIf access query string - apache

How do you access the query string from SetEnvIf? Somethig like:
SetEnvIf Query_String "p=path/to/file$" got_path
UPDATE:
In htaccess, I have:
SetEnvIf Request_URI !/folder/page1\.html$ NO_COOKIE
Header unset Cookie env=NO_COOKIE
RewriteRule (.*) /h.php?ref=$1 [L]
Basically, I ask h.php to take control of all user requests. And I use SetEnvIf to allow cookies only for /folder/page1.html.
However, it seems like Request_URI is always set to "h.php" and never to " /folder/page1.html" (maybe because of the redirection). For that reason I added ref=$1 to try to recognize which url it is being redirected from. Therefore I need to read the query string from SetEnvIf.
I hope I am making some sense.

You don't need to add a query string for this.
You can use:
# always start with NO_COOKIE=1
RewriteRule ^ - [E=NO_COOKIE:1]
# unset NO_COOKIE when URI is /folder/page1.html
RewriteCond %{THE_REQUEST} /folder/page1\.html
RewriteRule ^ - [E=!NO_COOKIE]
Header set NoCookie %{NO_COOKIE}e
RequestHeader set NoCookie %{NO_COOKIE}e

Related

How to add a header if the url contain any get parameter using htaccess file?

I am running PHP in Apache2 server. I would like to add header("X-Robots-Tag: noindex", true); to my pages if the url contains any get parameters like https://example.com/? or https://example.com/a.php? or https://example.com/a.php?key=value. So basically, if the url contain ? charter, the header needs to be added.
Is it possible to do it using .htaccess file and how to do it? Or is there any other way to achieve this?
Ref: https://yoast.com/x-robots-tag-play/
EDIT
Below are the existing rewrite codes;
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^nps-benchmarks/(.*)$ http://testing.mysite.com.s3-website-us-east-1.amazonaws.com/$1 [P]
RewriteRule ^agency/(.*)$ http://testing.mysite.com.s3-website-us-east-1.amazonaws.com/site/mod1/$1 [P]
RewriteRule ^apps/(.*)$ http://testing.mysite.com.s3-website-us-east-1.amazonaws.com/site/mod2/$1 [P]
RewriteRule ^help-each-other/(.*)$ http://testing.mysite.com.s3-website-us-east-1.amazonaws.com/site/mod3/$1 [P]
RewriteRule ^customers-help-each-other/(.*)$ http://testing.mysite.com.s3-website-us-east-1.amazonaws.com/site/mod4/$1 [P]
RewriteRule ^de/(.*)$ http://testing.mysite.com.s3-website-us-east-1.amazonaws.com/site/multilanguage/de/$1 [P]
RewriteRule ^es/(.*)$ http://testing.mysite.com.s3-website-us-east-1.amazonaws.com/site/multilanguage/es/$1 [P]
RewriteRule ^fr/(.*)$ http://testing.mysite.com.s3-website-us-east-1.amazonaws.com/site/multilanguage/fr/$1 [P]
RewriteRule ^(wp-content/themes/my-site/assets/)(css|js)(/.+)(-v\d+\.\d+)\.(min)\.(js|css)$ $1/$2/$3.$5.$6 [L]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
like https://example.com/? or https://example.com/a.php?
The issue in these two instances are that the query string is empty, so you can't check for this using the standard QUERY_STRING server variable ("empty" and "not-exists" evaluate to the same thing, ie. empty).
However, you can check for a literal ? (ie. query string delimiter) in the first line of the HTTP request headers, as contained in the THE_REQUEST Apache server variable.
In the case of the first example above, this will contain a string of the form:
GET /? HTTP/1.1
And for /a.php?key=value, this will be:
GET /a.php?key=value HTTP/1.1
We can use mod_rewrite to check this and set an environment variable. Then use the header directive to set the required X-Robots-Tag HTTP response header conditionally based on whether this env var is set.
For example, near the top of the root .htaccess file:
RewriteEngine On
# Check for literal "?" in URL and set QUERY_EXISTS env var
RewriteCond %{THE_REQUEST} \s/.*\?
RewriteRule ^ - [E=QUERY_EXISTS:1]
# Set header if QUERY_EXISTS is set
header set X-Robots-Tag "noindex" env=QUERY_EXISTS
This sets the header on 2xx "OK" responses. It won't, for instance, set the header on a 404 - but 404s are not indexed anyway, so the header is redundant. However, if you specifically need to set the header on all (non-2xx) responses then use the always condition. For example:
# Use "always" to set on non-2xx responses as well
header always set ....
Note that this is also dependent on other directives you might have in your .htaccess file. For example, if you have existing mod_rewrite directives that cause the rewrite engine to "loop" then the env var will be renamed to REDIRECT_QUERY_EXISTS and you will likely need to check for this instead in the header directive.

How to write an IF contains condition matching 2 ENV variables set via RewriteRules

To give context, the goal:
Using apache httpd I need to test a contextual segment of the request uri is contained within a cookie value sent in the header before redirect the user to a splash page for cookie confirmation, or allowing them access to the site.
Given the following:
url: http://www.example.com/en/gb/main.html
cookie: ;acceptedCookies=fr,en,de,it
If the language segment of the url = "en", and this is amongst the users acceptedCookies. Then allow the user access to the main site, else redirect the user to the splash page.
What I've tried:
SetEnvIf Host ^ uriCountryCode=NUL
SetEnvIfNoCase Request_URI "^(.+)?\/([a-zA-Z]{2})\/[a-zA-Z]{2}\/.+$" uriCountryCode=$2
SetEnvIf Host ^ acceptedCookieList=EMP
SetEnvIf Cookie "(^|;\*)acceptedCookies=([^;]+)?" acceptedCookieList=$2
#1st.
<If "%{acceptedCookieList} =~ %{uriCountryCode}">
// Doesn't work
</If>
#2nd.
<If "env('acceptedCookieList') =~ env('uriCountryCode')">
// No luck
</If>
#3rd.
<If "env('acceptedCookieList') =~ /env('uriCountryCode')/">
// Now I'm just guessing
</If>
#4th.
RewriteCond %{acceptedCookieList} !%{uriCountryCode}
RewriteCond %{REQUEST_URI} !^/en/gb/splash.html$ [NC]
RewriteRule ^(.+)$ /mt/en/splash [L,R=301]
I've recently learnt that some of these modules i.e env('x') won't load SetEnvIf variables dues to the SetEnvIf variables not loading early enough to be accessible but i'm trying to find a httpd solution to this my problem
mod_rewrite can set environment variables.
Use a 302 redirect (Moved Temporarily) instead of a 301 redirect (Moved Permanently).
Matching against an arbitrary regex provided by the client (i.e. the contents of the acceptedCookies cookie) is dangerous. Nevertheless, the httpd expressions language doesn't have a built-in "contains" function and so it's non-obvious how to avoid the regex matching. This will make your server(s) susceptible to DoS attacks.
All that said, consider something like:
RewriteCond %{HTTP_COOKIE} acceptedCookies=([^;]+)
RewriteRule ^.*$ - [E=COOKIE_ACCEPTED_LANGS:%1]
RewriteCond %{REQUEST_URI} ^/([^/]+)/.*$
RewriteRule ^.*$ - [E=URL_LANG:%1]
RewriteCond expr %{ENV:URL_LANG} =~ %{ENV:COOKIE_ACCEPTED_LANGS}
RewriteCond %{REQUEST_URI} !^/en/gb/splash.html$ [NC]
RewriteRule ^.*$ /mt/en/splash [R]
Following #Avi solution will work, but any solution allowing client-side values unknown in length to perform validation is fundamentally flawed, posing the potential risk of exceeding buffers and DOS.

Deny request with environment variable

I am using apache. I have a header variable which name is GEO_COUNTRY. I want something like that:
If GEO_COUNTRY == "USA" THEN DENY THE REQUEST
Is this possible with using .htaccess?
Ps: I know Stackoverflow rules, I researched it and nothing find so I couldn't try anything.
Here is how you can deny the request if env var GEO_COUNTRY is set and the value is usa
RewriteEngine on
RewriteCond %{ENV:GEO_COUNTRY} ^usa$ [NC]
RewriteRule ^ - [F,L]

set referrer header using query string on apache configuration

I need to take a parameter from the query string and set it in the referrer header in the Apache configuration file.
Do you know if this is possible?
I'm able to do the same with the cookies but I need to do it using the query string.
setEnvIfNoCase ^Cookie$ "(referrer=\w*:\/\/\w*)" HTTP_MY_COOKIE=$1
setEnvIfNoCase HTTP_MY_COOKIE "(http:\/\/.*\.\w*)" REFERRER=$1
RequestHeader set Referer %{REFERRER}e
Regards
The solution was quite simple.
setEnvIfNoCase or setEnvIf can't use the query string so is not possible to use the same trick i used for the cookies, the solution is a combination of RewriteCond with RewriteRule like in the example below:
RewriteCond %{QUERY_STRING} referrer=(.*)
RewriteRule ^/ - [env=REFERRER:%1]
RequestHeader set Referer %{REFERRER}e
i answered to my question so another user (if exist) with the same question can find an starting point.

How to use SetEnv with a URL parameter

I'm trying to implement language switching in .htaccess, and the only thing left now is to handle clients which don't support cookies. To do that, I must set prefer-language when the user clicks a link with a language parameter.
RewriteEngine On
RewriteBase /
RewriteCond %{QUERY_STRING} (?:^|&)language=(en|fr|no)
RewriteRule ^(.*)$ $1? [cookie=language:%1:.example.com,env=language:%1,R]
SetEnv prefer-language $language
The problem is with the last line - The value is always set to empty. It works if I hardcode it, but not if I try to refer to a variable. Is there some special syntax to refer to environment variables in this context, or is there some other way to set prefer-language?
Edit: Cross-posted to Apache users list.
You can set environment variables with mod_rewrite as well. Actually, you already did that (see env/E flag).
I can’t test it with mod_negotiation myself, but the following should work and set the prefer-language:
RewriteCond %{QUERY_STRING} ^((?:[^&]&)*)language=(en|fr|no)&?([^&].*)?$
RewriteRule ^ %{REQUEST_URI}?%1%3 [L,CO=language:%2,R]
RewriteCond %{HTTP_COOKIE} (^|[,\s])language=([^\s,;]+)
RewriteRule ^ - [L,E=prefer-language:%2]
SetEnvIf REDIRECT_prefer-language (.+) prefer-language=$1
But it would be far easier if you put the language identifier into the URL path like /en/…:
SetEnvIf Request_URI ^/(en|fr|no)/ prefer-language=$1
SetEnvIf REDIRECT_prefer-language (.+) prefer-language=$1
I don’t know if you need the additional/second SetEnvIf variable.
Looks like there's no support for variables in SetEnv, but here's a working configuration if someone else is trying to do the same. It's a simpler kind of language selection, since it just copies the language parameter from the referer to the current URL if it's not changed:
RewriteEngine On
RewriteBase /
# Keep the language parameter if specified in the last URL
RewriteCond %{HTTP_REFERER} ^(?:.*[&?])?language=(en|fr|no).*$
RewriteCond %{QUERY_STRING} !^(?:.*&)?language=(en|fr|no).*$
RewriteRule ^(.*)$ $1?language=%1 [redirect=permanent]
# Set the language from the URL parameter
RewriteCond %{QUERY_STRING} ^(?:.*&)?language=(en|fr|no).*$
RewriteRule ^ - [env=prefer-language:%1]
# Cache only when the language parameter is set
<IfDefine !prefer-language>
Header set Vary *
</IfDefine>