htaccess equivalent to PHP's $_SERVER['SERVER_NAME']? - apache

I have a need to dynamically input the current domain name, into an htaccess file. This would be trivial in PHP but I can't figure out how to do it in "Apache Speak" and my Apache-fu is weak.
For the record, I've tried this:
SetEnvIfNoCase Referer %{SERVER_NAME} internal
and this:
SetEnvIfNoCase Referer %{HTTP_HOST} internal
but frankly I'm not sure if I'm even on the right track at all. The end result I'm after would look something like:
SetEnvIfNoCase Referer currentdomain.com internal

Try asking yourself, is there a different approach to your problem?
If there isn't a simple answer, it's most likely that there is a different way to approach the situation.
For example, if you could insert it dynamically once and write the .htaccess with php, you could possibly save yourself trouble and maybe even efficiency in your code.

There isn't one. If you're running 2.4 then you can use SetEnvIfExpr, but 2.2 or earlier require some work with mod_rewrite.

You can do this:
SetEnvIfNoCase Referer www\.whateveryourdomain\.com internal
The syntax for SetEnvIfNoCase is like this:
SetEnvIfNoCase attribute regex [!]env-variable[=value] [[!]env-variable[=value]] ...
From Apache Docs
attribute can have:
An HTTP request header field (see RFC2616 for more information about these); for example: Host, User-Agent, Referer, and Accept-Language. A regular expression may be used to specify a set of request headers.
One of the following aspects of the request:
Remote_Host - the hostname (if available) of the client making the request
Remote_Addr - the IP address of the client making the request
Server_Addr - the IP address of the server on which the request was received (only with versions later than 2.0.43)
Request_Method - the name of the method being used (GET, POST, et cetera)
Request_Protocol - the name and version of the protocol with which the request was made (e.g., "HTTP/0.9", "HTTP/1.1", etc.)
Request_URI - the resource requested on the HTTP request line -- generally the portion of the URL following the scheme and host portion without the query string. See the RewriteCond directive of mod_rewrite for extra information on how to match your query string.
The name of an environment variable in the list of those associated with the request. This allows SetEnvIf directives to test against the result of prior matches. Only those environment variables defined by earlier SetEnvIf[NoCase] directives are available for testing in this manner. 'Earlier' means that they were defined at a broader scope (such as server-wide) or previously in the current directive's scope. Environment variables will be considered only if there was no match among request characteristics and a regular expression was not used for the attribute.
The same applies for SetEnvIfNoCase.

Related

Apache 2.4 Rewrite URL matching full URL

I'm using Apache 2.4 as Reverse Proxy, and I need to redirect to an URL, only if credential is passed into URL. For Example, this is my URL:
https://user:password#myserver.mydomain.com/site1.php?1
I use this Rewrite Condition:
RewriteCond %{HTTP_HOST} ^user:password#ohab\.marcolino7\.myds\.me$
But it do not match, i suppose because HTTP_HOST do not contain authentication data.
In there a way to match the URL with also authentication data and then so I can redirect?
Many Thanks
Marco
As you correctly say, that is not part of the host header, so wouldn't match like that.
You can do it using the REMOTE_USER variable. How you do it depends on the context of your rules. See the documentation and specifically the quote below.
%{LA-U:variable} can be used for look-aheads which perform an
internal (URL-based) sub-request to determine the final value of
variable. This can be used to access variable for rewriting which is
not available at the current stage, but will be set in a later phase.
For instance, to rewrite according to the REMOTE_USER variable from
within the per-server context (httpd.conf file) you must use
%{LA-U:REMOTE_USER} - this variable is set by the authorization
phases, which come after the URL translation phase (during which
mod_rewrite operates).
On the other hand, because mod_rewrite implements its per-directory
context (.htaccess file) via the Fixup phase of the API and because
the authorization phases come before this phase, you just can use
%{REMOTE_USER} in that context.
Something like this in your httpd.conf file:
RewriteCond %{LA-U:REMOTE_USER} =user
Or in .htaccess:
RewriteCond %{REMOTE_USER} =user

Using RedirectMatch with HTTP_HOST in the destination

I keep reading that, where possible, I should not be using mod_rewrite. As such, I am trying to do a http to https rewrite with RedirectMatch.
Question: How can I use RedirectMatch and use Apache server variables (such as %{HTTP_HOST}) in the URL parameter?
This code fails to return a response to the client (Chrome):
RedirectMatch ^(.*) https://%{HTTP_HOST}/$1
I recently asked a similar question to this, but it may have been too wordy and lacks direction for an answer: Redirecting http traffic to https in Apache without using mod_rewrite
If you're using 2.4.19 or later, the Redirect directive has a somewhat obscure feature: putting it inside a Location or LocationMatch will enable expression syntax.
So your example can be written as
<LocationMatch ^(?<PATH>.*)>
Redirect "https://%{HTTP_HOST}%{env:MATCH_PATH}"
</LocationMatch>
(Here, the ?<PATH> notation means that the match capture will be saved to an environment variable with the name MATCH_PATH. That's how we can use it later in the Redirect.)
It's even easier if you always redirect using the entire request path, because you can replace the capture group entirely with the REQUEST_URI variable:
<Location "/">
Redirect "https://%{HTTP_HOST}%{REQUEST_URI}"
</Location>
Now, is this easier to maintain/understand than just using mod_rewrite for this one case? Maybe not. But it's an option.
No, You can't use variables of that type with Redirect/RedirectMatch. If you need variables, such as %{HTTP_HOST}, use mod_rewrite.
Note: I commend you for not trying to use mod_rewrite right away, because most people will go for mod_rewrite even for the simplest of redirections, which is clearly overkill and most times it is just looking to complicate things unnecessarily.
Writing for users who might face the same in future.
Not sure how you are adding vhost entries.
I guess this vhost entries are added automatically with help of some programming script.
Do you use VhostDirective with ServerName?
<VirtualHost *:8080>
ServerName example.domain.com
</VirutalHost>
If so, then you can use the same domain value for populating RedirectMatch field.
If you are manually adding vhost entries just write that domain URL value explicitly instead of HTTP_HOST.
Or let me know if its a different scenario.

How to rewrite Location response header in a proxy setup with Apache?

I have a primary proxy which sends requests to a secondary proxy on which OpeenSSO is installed.
If the OpenSSO agent determines that the user is not logged in, it raises a 302 redirect to the authentication server and provides the original (encoded) URL that the user requested as a GET parameter in the redirect location header.
However, the URL in the GET variable is that of the internal (secondary) proxy server, not the original proxy server. Therefore, I would like to edit/rewrite the "Location" response header to give the correct URL.
E.g.
http://a.com/hello/ (Original requested URL)
http://a.com/hello2/ (Secondary proxy with OpenSSO agent)
http://auth.a.com/login/?orig_request=http%3A%2F%2Fa.com%2Fhello2%2F (302 redirect to auth server with requested URL of second proxy server encoded in GET variable)
http://auth.a.com/login/?orig_request=http%3A%2F%2Fa.com%2Fhello%2F (Encoded URL is rewritten to that of the original request)
I have tried pretty much all combinations of headers and rewrites without luck so I'm thinking it may not be possible. The closest I got was this, but the mod_headers edit function does not parse environment variables.
# On the primary proxy.
RewriteEngine On
RewriteRule ^/(.*)$ - [E=orig_request:$1,P]
Header edit Location ^(http://auth\.a\.com/login/\?orig_request=).*$ "$1http%3A%2F%2Fa.com%2F%{orig_request}e"
ProxyPassReverse
ProxyPassReverse should do this for you:
This directive lets Apache adjust the URL in the Location, Content-Location and URI headers on HTTP redirect responses.
I'm not sure why your reverse proxy isn't behaving this way already, assuming you're using a pair of ProxyPass and ProxyPassReverse directives to define it.
Editing the Location Header
If you want to be able to edit the Location header as you describe, you can do it as of Apache 2.4.7:
For edit there is both a value argument which is a regular expression, and an additional replacement string. As of version 2.4.7 the replacement string may also contain format specifiers.
The "format specifiers" mentioned in the docs include being able to use environment variables, e.g. %{VAR}e.
You might also want to consider modifying your application such that the orig_request URL parameter is relativized, thus potentially eliminating the need for Header edits with environment variables.
Relative Path Location Header
You can also try using a relative path in your Location header, which would eliminate the need to explicitly map one domain to the other. This is officially valid as of RFC 7231 (June 2014), but was was widely supported even before that. You can relativize your Location header using Apache Header edit directives (even prior to version 2.4.7, since it wouldn't require environment variable substitution). That would look something like this:
Header edit Location "(^http[s]?://)([a-zA-Z0-9\.\-]+)(:\d+)?/" "/"

Can you use mod_rewrite to remove user-agent

Our application has a filter that uses the user-agent of incoming requests to redirect to our mobile site if appropriate. We have recently added a page to our web app that should be referenced by all types. We will be adding whitelist functionality to the filter in the longer term but in the short term we would like a simple way to stop the filter from triggering.
If we can remove or overwrite the user-agent from the request we will achieve our short-term aim, but this needs to be done in such a way so to avoid redeploying. Something like a mod_rewrite rule would be ideal.
Can mod_rewrite, or something similar, do the job? It would need to be a standard apache module so we don't have to do more than add a line or two of config.
Adendum:
Looks like we can use the following combination (or something similar)
SetEnvIf REQUEST_URI "special/uri/path" delete_user_agent
RequestHeader unset User-Agent env=delete_user_agent
No, you cannot do it with mod_rewrite: it can use User-Agent header in conditions, but cannot change it. What you need perhaps is mod_headers.
This module provides directives to control and modify HTTP request and
response headers. Headers can be merged, replaced or removed.
The directive would probably look like this:
RequestHeader unset User-Agent
(You may need to use early here to process this header before mod_rewrite will).

How to get real request when using mod_rewrite

I'm wondering how to get the "real" requested URL, when using mod_Rewrite. There are several rewrite rules in my htaccess-file for caching-purposes: First there is a check, if a cache-file is existent. If so, the request will be rewritten to the cache-file. Otherwise the request will be rewritten to a php-script, which creates this cache-file.
But I suspect, the rules doesn't match like I want them to. Is there a possibility to trace the "real" requests to see, which URL was requested by the client and which file is requested in the background?
Thanks in advance.
You may want the %{THE_REQUEST} special variable. The mod_rewrite docs say this:
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.
So if someone enters http://your-domain/path/file.html into their browser and your webserver rewrites /path/file.html into something entirely different, the %{THE_REQUEST} variable will still be GET /path/file.html HTTP/1.1, or something similar.
As for what the request finally got rewritten to, you can turn on logging for rewrite to see what it is:
RewriteLog /some-path/rewrite.log
RewriteLogLevel 9
This would go in your virtual host config and only be used for debugging purposes. The rewrite.log file will contain details on the rewriting process and what the final URI is.