How to set url parameter in header - apache

I have a client request that cannot contains custom headers, but server-side I need a hearder (let's call him foo).
So I have this url path/to/bar?foo=value
I want that my apache conf that the foo value and put it in a header.
I haven't so far find a solution :(.

Finaly I find a solution
RewriteEngine On
RewriteCond %{QUERY_STRING} ^(?:.*&)?foo=(.*)$
RewriteRule ^ - [env=foo:%1]
<IfDefine !foo>
RequestHeader set Foo %{foo}e env=foo
</IfDefine>

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.

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]

apache SetEnvIf access query string

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

Is it possible to output any or all available variables in a .htaccess file?

I'm trying to a build a .htaccess file with some rewrite rules and would like to know what several variables actually contain when my request is handled. Is there anyway of seeing what their values would be when Apache handles the request?
E.g. print the contents of %{HTTP_USER_AGENT}
Sure. Create this sort of .php file (echo.php):
<?php
phpinfo(INFO_VARIABLES);
?>
Add this rule in .htaccess:
RewriteEngine On
RewriteCond %{REQUEST_URI} !echo.php
RewriteRule .* echo.php?ua=%{HTTP_USER_AGENT}&https=%{HTTPS} [L]
Add more parameters if necessary.
Now call any URL and check the output (the GET parameters should be on the top of table).
But, TBH, almost all of this info is received by Apache and is available to PHP anyway: look at $_SERVER.
Yes, it is possible to output the request variables through .htaccess.
You can do it by "hacking" a custom error status message. As long as you have AllowOverride set to FileInfo you can set and trigger a custom error response in your .htaccess file with the desired variables in the output:
ErrorDocument 404 "Request: %{THE_REQUEST} Referrer: %{HTTP_REFERER} Host: %{HTTP_HOST}"
RewriteRule ^ - [L,R=404]
For reference, a list of available variables is available in the Apache documentation.
Interestingly, you are not limited to using 400 or 500 error statuses for the error response override. You can even override the status 200 "ErrorDocument." That means you can do a lot more than just output variables for troubleshooting with this trick. Throw an <If> tag around it and you have a document!
<If "%{REQUEST_URI} =~ /compliance.html$/">
ErrorDocument 200 "<html><body><h1>Yes, Max. Those were geeks.</h1></body>"
RewriteRule ^ - [L,R=200]
</If>
Another way of achieving this without altering the behavior of your routes (no 404 or redirect) is to send the desired value as a response header.
RewriteRule .* - [ENV=REQUEST_URI:%{REQUEST_URI}]
Header set x-request-uri %{REQUEST_URI}e
Then you can see the output with curl -I
$ curl -I http://localhost:8095/api/my/request/uri
...
x-request-uri: /api/my/request/uri
Your route will still go to where it was supposed to go, but you get a response header with the value you wanted

How do I write SCRIPT_URI to a header in Apache?

I have a setup where I have servers like this:
load balancer -> Apache -> Tomcat
I would like Apache to write the url that the client used into a header, so I can read that once I hit tomcat.
I've tried to use mod_rewrite and mod_headers so do it, but with no luck.
if I look at http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html then it seems clear that i need the variable called SCRIPT_URI:
SCRIPT_URI=http://en1.engelschall.com/u/rse/
I also looked at this http://www.askapache.com/htaccess/crazy-advanced-mod_rewrite-tutorial.html so figure out how to write headers and have had some succes, but not enough.
I have php installed on the apache server, and if i look at phpinfo() i can see the SCRIPT_URI is there and has a sensible value.
I just can't get it to write it to a header. Here's a simplified version of what I've done:
#load modules
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule headers_module modules/mod_headers.so
#Get the original uri used
RewriteRule .* - [E=INFO_SCRIPT_URI:%{SCRIPT_URI},NE]
RequestHeader set x-orig-uri "%{INFO_SCRIPT_URI}e"
I've tried several other options and both on windows, cygwin and ubuntu linux
Any ideas?
I found a workaround myself, although it's not the clean and easy solution I wanted.
I was able to get the indvidual parts and can use them to build the full URI:
<IfModule !rewrite_module>
LoadModule rewrite_module modules/mod_rewrite.so
</IfModule>
<IfModule !headers_module>
LoadModule headers_module modules/mod_headers.so
</IfModule>
<IfModule rewrite_module>
<IfModule headers_module>
####### INITIAL SETUP #########################
RewriteEngine on
####### SET HEADERS #########################
#get and set the host name
RewriteRule .* - [E=INFO_HTTP_HOST:%{HTTP_HOST},NE]
RequestHeader set x-orig-host "%{INFO_HTTP_HOST}e"
#get and set the host port
RewriteRule .* - [E=INFO_SERVER_PORT:%{SERVER_PORT},NE]
RequestHeader set x-orig-port "%{INFO_SERVER_PORT}e"
#If the uri starts with a slash and some alphanumerics, then make a
#group of that until the first non-alpha (ie. the next slash)
RewriteCond %{REQUEST_URI} ^(/[\w-]+)
#Save the content of the regex match group ( %1 ) in an environment variable
RewriteRule .* - [E=INFO_REQUEST_CONTEXT:%1,NE]
#Set a header with the content of the environment variable
RequestHeader set x-orig-context "%{INFO_REQUEST_CONTEXT}e"
#If the accept-header contains a number after ;version= then make a regex group of that number
RewriteCond %{HTTP_ACCEPT} \+json;version=(\d+)$
#Save the content of the regex match group ( %1 ) in an environment variable
RewriteRule .* - [E=INFO_ACCEPT_VERSION:%1,NE]
#Set a header with the content of the environment variable
RequestHeader set x-orig-accept-version "%{INFO_ACCEPT_VERSION}e"
#If the accept-header contains kasia2. followed by some letters,
#then make a regex group of those letters
RewriteCond %{HTTP_ACCEPT} kasia2.(\w+).*
#Save the content of the regex match group ( %1 ) in an environment variable
RewriteRule .* - [E=INFO_ACCEPT_NAME:%1,NE]
#Set a header with the content of the environment variable
RequestHeader set x-orig-accept-name "%{INFO_ACCEPT_NAME}e"
#If https is on ...
RewriteCond %{HTTPS} on
#...then set the protocol environment variable to "https"
RewriteRule .* - [E=INFO_PROTOCOL:https,NE]
#If https is off ...
RewriteCond %{HTTPS} off
#...then we assume it must be "http"
RewriteRule .* - [E=INFO_PROTOCOL:http,NE]
#Finally, set the protocol header
RequestHeader set x-orig-protocol "%{INFO_PROTOCOL}e"
#Get the request uri and set an environment variable
RewriteRule .* - [E=INFO_REQUEST_URI:%{REQUEST_URI},NE]
#Build the whole original url out of the available parts. SCRIPT_URI is always null, otherwise we could have used that.
RequestHeader set x-orig-url "%{INFO_PROTOCOL}e://%{INFO_HTTP_HOST}e%{INFO_REQUEST_URI}e"
#In addition make an url with only the host and context, for convenience
RequestHeader set x-orig-url-base "%{INFO_PROTOCOL}e://%{INFO_HTTP_HOST}e%{INFO_REQUEST_CONTEXT}e"
</IfModule>
</IfModule>
According to https://serverfault.com/questions/23470/setting-apache-environment-variable-on-mod-rewrite-rewrite-condition, you need to tweak the order of execution by using different configuration sections
Here I added a dummy <Location> section
RewriteRule ^ - [E=FOO:set_by_rewrite_rule]
RequestHeader set x-foo-outside-location %{FOO}e
<Location "/bla">
RequestHeader set x-foo-in-location %{FOO}e
</Location>
and these are the headers that I'm getting
x-foo-in-location='set_by_rewrite_rule'
x-foo-outside-location='(null)'
Note that I get both headers to null if I use <Location "/"> (and that I'm unable to find a solution valid for all request paths)
Note also that Sebastian's answer is getting the env variables in the header without any dummy configuration section... Go figure!