Setting env variable in httpd and accessing them in Response headers - mod-rewrite

I have the following conf. I am trying to set a cookie with a value which I extracted in the rewrite rule. But the value of the cookie being always set to null. Is it a problem with the regex or I am trying to do something wrong here. I am completely new to apache httpd.
RewriteEngine On
RewriteCond %{QUERY_STRING} ^(.*)uname=(.*)
RewriteRule ^/(.*)&uname=(.*)$ /$1 [env=GRAFANA_UNAME:%2,L,PT]
RewriteCond %{HTTP_COOKIE} uname=(.*)
RewriteRule ^(.*)$ "-" [env=GRAFANA_UNAME:%1,L,PT]
RequestHeader set X-WEBAUTH-USER %{GRAFANA_UNAME}e
RequestHeader unset Authorization
ProxyRequests Off
ProxyPass "/" http://localhost:3000/
ProxyPassReverse "/" http://localhost:3000/
Header always set Set-Cookie "uname=%{GRAFANA_UNAME}e;path=/;HttpOnly"
When I do uname=%{GRAFANA_UNAME}e the cookie value is being set to null always. How do I get the value of uname in the response header.

Your rules imply these directives are not in htaccess, but my assumption is that an internal redirect happens nonetheless before your request is really processed.
Try accessing REDIRECT_GRAFANA_UNAME. That prefix is added each time an internal redirect occurs to differentiate between the environment of the current and previous request.

Related

Force RewriteRule to end processing/looping in htaccess file

Yesterday I discovered that my server's response to non-supported HTTP methods was incorrect. If an HTTP method is not supported you're supposed to respond with an HTTP 405: Method Not Supported. Pandurang was able to answer that question.
I've done a lot of reading about how [L] loops and I had spent time going through all the Apache 2.4 flag documentation.
I tried using the [L] flag and then the [END] flag.
I tried to combine flags in every possible way (e.g. [L,R=405], [END,R=405]) on both RewriteRule sets.
I tried combinations where flags where absent.
I rearranged the order of the rules.
I tried adding RewriteCond %{REQUEST_METHOD} ^(GET|POST)$ before the unrelated second RewriteRule.
I did a lot of reading.
Here are the two set of rules:
RewriteEngine On
RewriteCond %{REQUEST_METHOD} !^(GET|POST)$
RewriteRule .* - [R=405]
#Unrelated rule, when present, breaks the above HTTP 405 turning it in to an HTTP 302:
RewriteRule !\.(css|js|zip)$ index.php [L]
To do testing I ran the following command using cURL:
curl -X PUT -d arg=val -d arg2=val2 https://www.example.com/ -i
I know the HTTP 405 code works via cURL because I can see the response code, just not when the other line is present and I have to have both. What do I need to do to force Apache to stop looping/processing once it matches a rule?
For some reason the new code must be at the bottom, which makes no sense as I'd like to avoid having Apache process all of the other rules to only end up doing this.
#Unrelated rule
RewriteRule !\.(css|js|zip)$ index.php [L]
#Rule that now works, only at the bottom
RewriteCond %{REQUEST_METHOD} !^(GET|POST)
RewriteRule .* - [R=405,L]

Replace key-value pair in query string with Apache2

I am trying to set a simple replacement in my URL query strings.
I have an absolute path in my query string I would like to be replaced by a custom string.
FROM http://acme.com/a/path?file=DIR/this.file&foo=2
TO http://acme.com/a/path?file=/long/absolute/path/to/this.file&foo=2
These are my directives:
# [sudo a2enmod rewrite]
RewriteCond %{QUERY_STRING} ^(.*)file=DIR(.*)$
RewriteRule ^/a/path /a/path?%1file=/long/absolute/path/to%2
With such a configuration, replacement does not work, DIR passes through.
I configured a LogLevel to trace1 in my Apache2 configuration but I get nothing in my access.log and no useful feedback in error.log.
The question is:
References:
https://wiki.apache.org/httpd/RewriteQueryString
https://httpd.apache.org/docs/current/rewrite/remapping.html
This works for me(I've added flags R and L):
RewriteEngine on
RewriteCond %{QUERY_STRING} ^(.*)file=DIR(.*)$
RewriteRule ^/a/path /a/path?%1file=/long/absolute/path/to%2 [R,L]
See also https://httpd.apache.org/docs/2.4/rewrite/flags.html

Configuring MODx Revolution to work with both http and https

I have a website using MODx Revolution (2.2.10-pl, advanced install), let's call it www.example.com, which I want to be accessible with both http and https.
to achieve this, I tweaked the site_url context setting to be [[++url_scheme]]www.example.com/. Links created using [[~id]] seem to be alright, however, sometimes, the generated links are really weird. My interpretation is that the code to create links programmatically doesn't work with my settings, but I don't know why, or how else I would go about enabling both http and https.
Question first, examples below: How should I set the site_url or any other site/context setting so that links on my site work with both http and https? Optionally, is the behavior I see a bug, or expected behavior given Revolution's tag evaluation semantics?
Misbehavior examples:
When I click on "View" in the manager for a resource with the alias example, the address that is opened is
https://www.example.com/xyz/[[++url_scheme]]www.example.com/example/
where xyz is my manager URL. The expected URL is of course
https://www.example.com/example/
Another case where this happens is for failed logins; my login call looks like this (minus irrelevant parts):
[[!Login? &redirectToOnFailedAuth=`[[++unauthorized_page]]`]]
The unauthorized_page's expected full URL is
https://www.example.com/special/401
but the URL which is opened for a failed login as username is
https://www.example.com/[[++url_scheme]]www.example.com/[[++url_scheme]]www.example.com/special/401?u=username
The second example is the same for http, except for the scheme, of course; I haven't logged into the manager with http.
EDIT
.htaccess at the webroot:
RewriteEngine On
RewriteBase /
# redirect all requests to /en/favicon.ico to /favicon.ico
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(en)/favicon.ico$ favicon.ico [L,QSA]
#RewriteRule ^(en|nl|de)/favicon.ico$ favicon.ico [L,QSA]
# redirect all requests to /en/assets* /assets*
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(en)/assets(.*)$ assets$2 [L,QSA]
#RewriteRule ^(en|nl|de)/assets(.*)$ assets$2 [L,QSA]
# redirect all other requests to /en/*
# to index.php and set the cultureKey parameter
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(en)?/?(.*)$ index.php?cultureKey=$1&q=$2 [L,QSA]
#RewriteRule ^(en|nl|de)?/?(.*)$ index.php?cultureKey=$1&q=$2 [L,QSA]
.htaccess in the manager's directory:
RewriteEngine On
RewriteBase /
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://www.example.com/xyz/$1
The problem is with $modx->makeUrl(). For example, for the
[[!Login? &redirectToOnFailedAuth=`[[++unauthorized_page]]`]]
call, in core/components/login/controllers/web/Login.php:
public function checkForRedirectOnFailedAuth(modProcessorResponse $response) {
$redirectToOnFailedAuth = $this->getProperty('redirectToOnFailedAuth',false,'isset');
if ($redirectToOnFailedAuth && $redirectToOnFailedAuth != $this->modx->resource->get('id')) {
$p = array(
'u' => $this->dictionary->get('username'),
);
$message = $response->getMessage();
if (!empty($message)) $params['m'] = $message;
$url = $this->modx->makeUrl($redirectToOnFailedAuth,'',$p,'full');
$this->modx->sendRedirect($url);
}
}
the last two lines do a redirect to a URL generated with makeUrl, which will be something like [[++url_scheme]]www.example.com/etc (note: I'm not 100% sure here, as I can't easily look at the raw URL. The conclusions still hold, though). If the URL is simply shown on the page, this is no problem, because MODx will parse the tag before inserting it into the html output. However, as the URL is used directly for the redirect, no such replacement takes place, and the browser interprets it as a relative URL, resulting in target URLs such as https://www.example.com/[[++url_scheme]]www.example.com/etc.
So much for the problem. To avoid this, site_url must be a literal value without any tags in it. As a workaround, I now use the following snippet as the first thing in my template:
$modx->config['site_url'] = $modx->config['url_scheme'] . substr($modx->config['site_url'], strlen('[[++url_scheme]]'));
return '';
together with a [[++site_url]] of
[[++url_scheme]]www.example.com/
Note that some parts of MODx don't seem to notice this update, which is why it's important to still use [[++url_scheme]] in your site_url. As far as I can tell right now, the parts that don't see the update, stuff like [[~id]], work properly with url_scheme.
EDIT this does of course only fix the "View" buttons in the manager if you tweak the manager templates accordingly.
WARNING this is of course very hacky, and not yet tested very well. The fact that some features do not see the overwritten value means that you're introducing an inconsistency into your website, which may lead to subtle errors! If a more clean solution comes up, go for it!

rewriting URLs from .json to .php

I want http://server/path/app.json?a=foo&b=bar to map to http://server/path/foo.php?a=foo&b=bar using mod_rewrite. I have the following incantation in my .htaccess which doesn't give any joy
RewriteEngine On
RewriteRule ^([^.?]+).json(.*)$ $1.php$2 [L]
Suggestions?
Update: Adding rewrite.log and error.log output (comments don't allow formatting)
I get the following in the rewrite.log
strip per-dir prefix: /Users/user/Sites/dir/app.json -> app.json
applying pattern '^([^.?]+).json(.*)$' to uri 'app.json'
rewrite 'app.json' -> 'app.php'
add per-dir prefix: app.php -> /Users/user/Sites/dir/app.php
internal redirect with /Users/user/Sites/dir/app.php [INTERNAL REDIRECT]
and the apache server log says
The requested URL /Users/user/Sites/dir/app.php was not found on this server.
If I read your question correctly you want:
http://server/path/app.json?a=foo&b=bar
Going to:
http://server/path/foo.php?a=foo&b=bar
Sowhen you capture (app).json $1 is app and $2 is your second parenthesis, it's ... nothing (the part between json and the ?). As everything after the question mark is the QUERY STRING and cannot be captured here. Your rewriteRule is working on the requested file, not on the QUERY STRING. So you didn't captured foo anywhere. For the QUERY_STRING you could use the [QSA] flag on the rewriteRule, that would simply append a=foo&b=bar after your rewrite.
RewriteEngine On
RewriteRule ^([^.?]+).json(.*)$ $1.php$2 [L]
Here you tell apache to reuse $1 (the filename without .json), so app.json will get redirected to app.php, not foo.php.
RewriteEngine On
RewriteRule ^([^.?]+).json(.*)$ $1.php [L,QSA]
Will redirect app.json?a=b&z=r to app.php?a=b&z=r.
Now if you really need to capture foo as the first QUERY_STRING parameter the rule will become harder. But you could do it like that (here instead of the first parameter I detect the parameter 'a=' and capture his value in %4):
RewriteCond %{QUERY_STRING} (.*)(^|&|%26|%20)a(=|%3D)([^&]+)(.*)$
RewriteRule ^([^.?]+).json$ %4.php? [L,QSA]

mod_rewrite issues

I have used the mod_rewrite module but was not able to redirect to the target page - I am getting an error:
The requested URL /old.html was not found on this server.
Rewrite rules as follows:
RewriteEngine On
RewriteRule ^/IN/index.html$ /IN/index.iface [L]
You need to request a URL with a path that’s matched by the pattern of your RewriteRule directive. So in your case obviously /IN/index.html (where the . can actually be any character, as it’s not escaped).

Resources