Apache config read header value - apache

Is there a way to read the value of a request header in Apache config? I want to avoid going into the .htaccess file and even better if I could avoid using SetEnvIf.
I'm trying to implement the suggestion here: https://stackoverflow.com/a/1850482/138228
I can't really find much on this topic outside of using regex. What I'm looking for is something like :
Header set NAME = %{value_of_different_header}%

Reading answer from : https://serverfault.com/questions/136428/header-set-access-control-allow-origin-not-working-with-mod-rewrite-mod-jk
It seems the solution is:
SetEnvIf Origin "http(s)?://(domaine1\.com|domain2\.com)$" AccessControlAllowOrigin=$0
Header always set Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
But this has nothing to do with .htaccess, you can put such lines in regular apache configuration file (virtualhost?) without using the bad .htaccess dynamic configuration files.
The value part of the Header instruction is:
value may be a character string, a string containing format specifiers or a combination of both
But the only format specifiers available are %% (for %), %t for a timestamp, %D (idem), %{foo}e and %{foo}s for environments variables.
SetenvIf is a good apache tool to read a request header, here reading the Origin header. Then, using environment variables is the classical way of writing complex things in Apache (I mean the way to store some sort of variables).
So I don't know why you would like another solution.

I couldn't find a away of doing this without SetEnvIf but other than that just copying a different header can be done with the following, I was doing this as part of a ReverseProxy (hence using RequestHeader instead of Header) but the two appear to be interchangeable
###This reads the value of OldHeader into TempValue
SetEnvIf OldHeader ".+" TempValue=$0
###This will overwrite the value of "NewHeader" if it was already set
RequestHeader set NewHeader %{TempValue}e env=TempValue
###Optionally remove the original
RequestHeader unset OldHeader

Related

How to handle (REAL) blank space in Apache?

I know there are many questions like that in stackoverflow. But it is actually different :)
My problem is that Apache (2.4.6) just cannot handle white spaces in a url for instance aspecially used by cURL. Well consider I have a URL like following:
http://10.0.0.1:1234/Some Service/Root?func=getMessage
IF I browse this URL in any popular browser, they change the white space (' ') to %20. And in that way Apache can handle the request (or wget also does so).
However, when I use cURL, it does not change to %20 and in that case Apache return Error 400. I think the reason is, in the end of the GET Url, there is a white space and then specifies the used HTTP protocol comes.
such as:
GET Some Service/Root?func=getMessage HTTP1.1
The problem is I cannot touch or perform any update on cURL site. For example, I cannot perform a sed operation before cURL request. So consider like cURL site is like a blackbox. I have no control on that site. Therefore, I really have to solve this problem only in Apache. Unfortunately, It is the only option for me.
RewriteRules that I found work with if URL contains %20 instead of real white space (' '). For example \s only for if I write down %20 in the curl request. For example:
curl -v "http://10.0.0.1:1234/Some%20Service/Root?func=getMessage"
But if I use like:
curl -v "http://10.0.0.1:1234/Some Service/Root?func=getMessage"
then it gets Erro 400 because of the space.
For example following solution for %20 exists if there is one space or more then one:
#executes repeatedly as long as there are more than 1 spaces in URI
RewriteRule "^(\S*)\s+(\S* .*)$" $1+$2 [N,NE]
#executes when there is exactly 1 space in URI
RewriteRule "^(\S*)\s(\S*)$" /$1+$2 [L,R=302,NE]
So my link may not as simple as following:
http://10.0.0.1:1234/Some Service/Root?func=getMessage
Probably it may include one space :) but there will be more than one parameters like
http://10.0.0.1:1234/Some Service/Root?func=doSomething&id=123&pid=123&message=blabla&name=john&surname=doe
But in any case, ofcourse, I need also prevent possible problems if there is more then one blank.
Thanks in advance
It seems that Nginx can handle blanks or white spaces. Nginx does not give 400.

Header set with query_string

I am runing apache and I am trying to set a header Foo=bar only when the request has a variable "q" on the query string. I would like something like this in my htaccess:
<RequestUri "q=">
Header set Foor "bar"
</RequestUri>
Of course it does not work. I already tried using "Location" and "LocationMatch" but those are not allowed inside the htaccess. So how can I do that?
If you are using Apache 2.4, you can do something like this
<If "%{QUERY_STRING} =~ /q=.*?/">
Header set Foo "bar"
</If>
https://httpd.apache.org/docs/2.4/mod/core.html#if
https://httpd.apache.org/docs/2.4/expr.html#examples
Just to expand on this further if you want to set the header's value dynamically according to the value of the query string you can capture regex groups.
For example if you have a "_locale" variable in your URL and you want to capture its value for a header you could use:
<If %{QUERY_STRING} !~ m#_locale=([a-z]{2})#">
RequestHeader set locale "$1"
</If>
(Assuming the value will be two lower case letters.)
This could match "_locale=en" in the query string then copy "en" to header "locale".

What's the opposite of "Header append Vary User-Agent", how to remove the "User-Agent" string from "Vary"?

I know that I can add the User-Agent to the Vary http header with this line in my .htacess:
Header append Vary User-Agent
But how can I remove the User-Agent from the Vary header if it is already set?
According to the mod_headers doc there is an append option, but no equivalent "remove" option.
Simple answer below, but you need some shenanigans to avoid sending an empty Vary: header (try to avoid it out of paranoia)
Header edit Vary (.*)User-Agent(.*) $1$2
# Remove leading or trailing ',' without making things complex above
Header edit Vary ^,?(.*),?$ $1
# 2.4-only: remove empty Vary header
Header unset Vary "expr=resp('Vary') =~ /^$/"
x-never-match can be any unlikely-to-ever-be-used header name.
Though this is not as generic as being able to remove the specific User-Agent keyword, it gets the job done:
Header set Vary "Accept-Encoding"
This will overwrite your existing header so that the vary header will only have Accept-Encoding

Understanding htaccess Filesmatch code

I am trying to install drupal in a subdirectory on my bluehost hosted website...
It's a HUGE pain
I'm thinking the following lines from the .htaccess is the problem. When I currently navigatoe to mysite.com/subdir/install.php I get a 403 error. However, when I take out "deny" from the lines below, I cease to get that error, so I suspect that this line is causing all the trouble.
My question is, can someone help me understand what is happening in the following code? Especially if you can break it down by component.
<FilesMatch "\.(engine|inc|info|install|make|module|profile|test|po|sh|.*sql|theme|tpl(\.php)?|xtmpl)(|~|\.sw[op]|\.bak|\.orig|\.save)?$|^(\..*|Entries.*|Repository|Root|Tag|Template)$|^#.*#$|\.php(~|\.sw[op]|\.bak|\.orig\.save)$">
Order allow,deny
</FilesMatch>
FilesMatch allows you to match files using a regular expression.
On your above FilesMatch you have 4 sets of regular expression where the 1 set have an secondary optional set.
Basically what it is doing is forbidden access (error 403) to any of the files found that are described on your sets of regex.
For example:
\.(engine|inc ...)$|
Means if the file ends with .engine or .inc or ... rest of the rule, deny access to it.
Then at the end of the first set of rules you have a | which like the above example, stands for OR so if the first set of rules were not match, it starts the second one, which is slight different.
^(\..*|Entries.*|Repository)$
Here it does the opposite, it matches if the file starts and end with a given keyword, so for example:
If file starts with . followed by anything the (.*) means anything else for example .htaccess or starts with Entries followed by anything or is exactly Repository or ... till the end.
Then the next rule ^#.*#$, this one means the file starts and ends with a # as # its treated literally
And the last set of rules does the same of the first verify if file ends with those given extensions.
If you want to know more then I suggest you to learn more about Perl Compatible Regular Expressions (PCRE)

Regex rule to match % sign in url for apache mod rewrite

Hello my rewrite rule is failling sometimes because my urls have % signs in them.
For example this url:
http://www.chillisource.co.uk/product/Grocery/Dr.%20Burnoriums%20Psycho%20Juice/1/B005MSE5KG/Psycho_Juice_70%_Ghost_Pepper
This is my rewrite rule:
RewriteRule ^product/([a-zA-Z]+)/([\sa-zA-Z0-9\-\+\.]+)/([0-9]+)/([A-Z0-9]+)/([a-zA-Z0-9]+) /product?&cat=$1&q=$2&page=$3&prod=$4&prodName=$5
How can I modify the 5th rule ([a-zA-Z0-9]+) to not fail on when there is a % in the product name ?
Thanks in advance.
Perhaps, it's not %20, but space. That is, the URL passed to rewrite adter urldecoding. If not, then just add percent sign to the range. (if yes — space).
---- Forget this part, I misunderstood the question ----
From what I get from the mod_rewrite documentation (http://httpd.apache.org/docs/current/mod/mod_rewrite.html), you should not have to deal with hex encoded characters (I assume that from the following statement:
THE_REQUEST
The full HTTP request line sent by the browser to the server (e.g., "GET /index.html HTTP/1.1"). This does not include any additional headers sent by the browser. This value has not been unescaped (decoded), unlike most other variables below.
In fact, using mod_rewrite would be practically impossible since you'd have to deal with that EVERYWHERE, e.g., you can always write %41 instead of 'A'.
--- But the following still is true ---
But your rewrite rule can't work, at least not with the request URL you posted: The last part of the regex "([a-zA-Z0-9]+)" is FAR too strict. In this case, it fails for the following reasons:
It lacks a treatment of the percent sign, as in "70%"
You forgot to include the underscore "_"
Try adding at least these two characters ("[a-zA-Z0-9%_]+") and it should work.