How to change a cookie name with mod_rewrite? - apache

I'm trying to change the name of a cookie that's set by an AWS ELB, but keep its value with a rewrite condition and rewrite rule.
Here's what I've managed so far:
RewriteCond %{HTTP_COOKIE} AWSELB=(^BD.*) [NC]
RewriteRule ^(.*) - [CO=SIMELB:%1:.amazonaws.com:lifetime:-1]
Obviously the RewriteRule is incorrect, but could someone help me with the right syntax?

Ok, following the comment thread, I think there's enough info to get started. Foremost, your
pattern doesn't work because of the (^BD.*) capture group, and in particular because of
the ^ anchor. Instead, capture (BD[^;]+) to grab everything up to the next ; (or the
end of the string if there isn't one).
To explicitly unset the previous cookie, other examples use the INVALID modifier, though I
cannot find the documentation for it.
Apache mod_rewrite documentation on
Cookies
RewriteCond %{HTTP_COOKIE} AWSELB=(BD[^&]+) [NC]
# Delete the old one
RewriteRule ^ - [CO=AWSELM:INVALID:.amazonaws.com:0:/:-1]
# Add the new one
# Specify your lifetime in minutes or 0 for the browser session (60 below)...
# ALso add the path
# Assumimg the -1 is for insecure cookies
RewriteRule ^ - [CO=SIMELB:%1:.amazonaws.com:60:/:-1]
For the old cookie to be successfully unset, both the domain and the path will need to
exactly match those originally set by AWS. Inspect the cookies currently being set and make
sure you match the domain & path.
And really, it isn't necessary to match BD... You could just as well do AWSELB=([^;]+) because it must only match up to the following semicolon anyway.
Addendum:
If the value is being lost, it may be because the the RewriteCond is only applied to the first subsequent matching RewriteRule. You can always just repeat the RewriteCond. This is ugly, unfortunately, but I tested it and found it to work correctly.
# no capture group the first time since you don't use it until later
RewriteCond %{HTTP_COOKIE} AWSELB=BD.+ [NC]
RewriteRule ^ - [CO=AWSELM:INVALID:.amazonaws.com:0:/:-1]
# This will continue to execute since the previous didn't have [L]
RewriteCond %{HTTP_COOKIE} AWSELB=(BD[^&]+) [NC]
RewriteRule ^ - [CO=SIMELB:%1:.amazonaws.com:60:/:-1]
(Note: you won't see the cookie value updated until a subsequent HTTP request; that is, if you tried to inspect it from your script right after setting it with Apache, the new value won't be present because the cookie header has to make a round trip back to the client)

Instead of trying to rewrite the cookie name, I tested with mod_header directives and seem to have addressed my issue with Amazon's ELB cookie breaking session affinity with another Amazon ELB.
RequestHeader edit Cookie AWSELB SIMELB
RequestHeader edit Cookie APPELB AWSELB
Header always edit Set-Cookie AWSELB APPELB
Header edit Set-Cookie AWSELB APPELB
This so far seems to work, relying on the browser to maintain the memory for me because after the retrieving the value of the first AWSELB on request, when I get the set-Cookie response back from the second AWSELB, the browser sees APPELB={value} and recalls the correct request cookie obtained from the first AWSELB.

Related

htaccess url redirect with get parameters ID and reduce value

I want to do an url redirect to a new domain by retrieving the ID parameter but only taking the first 4 characters. Anyone know how to do this?
For example, an original url:
http://www.original.example/see/news/actualite.php?newsId=be9e836&newsTitle="blablabla"
To :
https://www.new.example/actualites/be9e
I have tested :
RewriteCond %{QUERY_STRING} ^newsId=(.*)$ [NC]
RewriteRule ^$ https://www.new.example/actualites/%1? [NC,L,R]
RewriteCond %{QUERY_STRING} ^newsId=(.*)$ [NC]
RewriteRule ^$ https://www.new.example/actualites/%1? [NC,L,R]
There are a couple of problems with this:
The regex ^$ in the RewriteRule pattern only matches the document root. The URL in your example is /see/news/actualite.php - so this rule will never match (and the conditions are never processed).
The regex ^newsId=(.*)$ is capturing everything after newsId=, including any additional URL parameters. You only need the first 4 characters of this particular URL param.
As an aside, your existing condition is dependent on newsId being the first URL parameter. Maybe this is always the case, maybe not. But it is relatively trivial to check for this URL parameter, regardless of order.
Also, do you need a case-insensitive match? Or is it always newsId as stated in your example. Only use the NC flag if this is necessary, not as a default.
Try the following instead:
RewriteCond %{QUERY_STRING} (?:^|&)newsId=([^&]{4})
RewriteRule ^see/news/actualite\.php$ https://www.new.example/actualites/%1 [QSD,R,L]
The %1 backreference now contains just the first 4 characters of the newsId URL parameter value (ie. non & characters), as denoted by the regex ([^&]{4}).
The QSD flag (Apache 2.4) discards the original query string from teh redirect response. No need to append the substitution string with ? (an empty query string), as would have been required in earlier versions of Apache.
UPDATE:
I have an anchor link (#) which is added at the end of the link, is there a possibility of deleting it to make a clean link? Example, currently I have: https://www.new.example/news/4565/#title Ideally : https://www.new.example/news/4565
The "problem" here is that the browser manages the "fragment identifier" (fragid) (ie. the "anchor link (#)") and preserves this through the redirect. In other words, the browser re-appends the fragid to the redirect response from the server. The fragid is never sent to the server, so we cannot detect this server side prior to issuing the HTTP redirect.
The only thing we can do is to append an empty fragid (ie. a trailing #) in the hope that the browser discards the original fragment. Unfortunately, you will likely end up with a trailing # on your redirected URLs (browser dependent).
For example (simplified):
:
RewriteRule .... https://example.com/# [R=301,NE,L]
Note that you will need the NE flag here to prevent Apache from URL-encoding the # in the redirect response.
Like I say above, browsers might handle this differently.
Further reading:
URL Fragment and 302 redirects
redirect is keeping hash
How to clear fragment identifier on 302 redirect?

Best practice for a .htaccess internal path rewrite?

We have spend a considerable amount of time looking for a solution else where. We have read and tried the recommended threads. We most likely have a core misunderstanding as to why this, or something along these lines, does not work.
We get a request for a domain:
subdomain.domain.com/embed/34acb453bc4a53abc
We want to leave the URL as it is, but need to direct this to an internal vhost:
embed.example.com/34acb453bc4a53abc
Once the request is directed to this, our system can interpret the 34acb453bc4a53abc and return the appropriate data.
We tried the following (and variations of it) we just get nothing to work.
RewriteCond ^embed\/(.*)$ [NC]
RewriteRule ^ https://embed.example.com%{REQUEST_URI} [L,NE,P]
internal path rewrite
Just to clarify, you can't internally rewrite the request across different hosts. You need to configure a reverse proxy using mod_proxy and related modules. This is what the P flag on the RewriteRule directive is doing... it's passing the request to mod_proxy (providing this is already correctly configured in the server config).
RewriteCond ^embed\/(.*)$ [NC]
RewriteRule ^ https://embed.example.com%{REQUEST_URI} [L,NE,P]
However, this will send the request to https://embed.example.com/embed/34acb453bc4a53abc, not https://embed.example.com/34acb453bc4a53abc as you require.
You need to capture the part of the URL-path after /embded/ and use that instead. You are already capturing this in the RewriteCond directive, but you are not using it. You don't actually need the RewriteCond directive here.
Try the following instead:
RewriteCond %{HTTP_HOST} =subdomain.domain.com
RewriteRule ^embed/([a-z0-9]+)$ https://embed.example.com/$1 [P]
You state that the request is for subdomain.domain.com, so I've included that in the directive.
The L and NE flags are not required here. P implies L and there is nothing that requires the substitution to not be URL encoded. Slashes do not carry any special meaning in the regex, so do not need to be escaped.
I've also made the regex that matches the "code" more restrictive, rather than matching literally anything.
The $1 backreference then matches just the "code" that follows /embed/ in the URL-path.
Note that the order of directives is important. It needs to be before any directives that are likely to result in a conflict.
If the embed and subdomain hosts point to the same place on the filesystem then you can avoid the complexities and overhead of mod_proxy and simply "rewrite" the request on the same host.

Apache2: mod_rewrite with circular rewriting

I want to load a private site for an specific subdomain without creating a new virtual host (for not creating and repeating the virtual host configuration), in the following way:
The user writes priv.mydomain.com
The mod_rewrite appends /priv to the URL without redirection.
An Alias directive gets /priv and loads /other_system_path/private
The private page is loaded but the user sees no changes in the URL.
My current config is as follows (inside the proper virtual host):
Alias /priv /other_system_path/private
RewriteEngine on
RewriteCond %{HTTP_HOST} ^priv\.mydomain\.com$
RewriteRule (.*) /priv [PT]
The PT flag is, if I'm not wrong, for repeating the process of URL mapping, which turns into being got for the RewriteRule again, since priv. remains in the URL.
How can I achieve this?
The PT flag is, if I'm not wrong, for repeating the process of URL
mapping, which turns into being got for the RewriteRule again, since
priv. remains in the URL
You can skip the rule for the subrequests by adding the following condition
RewriteCond %{IS_SUBREQ} false
According to manual
IS_SUBREQ
Will contain the text "true" if the request currently being
processed is a sub-request, "false" otherwise. Sub-requests may be
generated by modules that need to resolve additional files or URIs in
order to complete their tasks.
ps: and you need, as I think, RewriteRule ^/?(.*)$ /priv/$1 [PT], so that any request will be transformed to the correct one, not just to the 'root' of the alias.

Apache mod_cache: Vary cache based on cookie values

Currently, I am using mod_cache to cache the page details of a web application.
I have the cache Vary based on User-Agent and Accept-Language, since there are different payloads for those situations.
Vary: User-Agent, Accept-Language
We have plans to have region-specific information on each page, but this is where we are trying to determine our caching strategy.
We have a cookie that persists to indicate the region we geolocated for, but obviously the cache does not vary based on this cookie.
It is possible to vary based on the value for certain cookies or headers in general? (Note I say certain cookies, as we wouldn't want the session identifier to collide with this) - something like a regex match to this:
location=(.+?);
That is possible using Apache. It can parse cookie value and pass it to custom header, then you need to Vary by this header:
# Set languageC cookie value to environment variable "siteLanguage"
RewriteCond %{HTTP_COOKIE} ^.*lunetics_locale.*$ [NC]
RewriteCond %{HTTP_COOKIE} (?:^|;\s*)lunetics_locale=([^;]*) [NC]
RewriteRule ^(.*)$ - [env=siteLanguage:%1]
# If no languageC cookie present. Set "siteLanguage" environment variable to "en"
RewriteCond %{HTTP_COOKIE} !^.*lunetics_locale.*$ [NC]
RewriteRule ^(.*)$ - [env=siteLanguage:en]
# Set enviroment variable "siteLanguage" value to custom header "SiteLanguage"
RequestHeader set X-Language "%{siteLanguage}e" env=siteLanguage
and add Vary X-Language to your response headers.
I'm not sure this is a best way, I have related question and problems with this: Is it possible to vary page caches (to have cache versions) with the same url and different cookie value (language)?

apache rewrite map redirect to 404

My Situation:
I implemented an apache Rewrite Map to redirect incoming requests based on a database
RewriteEngine On
RewriteMap dbapp prg:/usr/local/somewhere/dbapp.rb
RewriteRule ^/(pattern)$ ${dbapp:$1} [R]
So far everything works fine, but I want to decide in the dbapp.rb script weather to redirect or give the client a http-status-code-404. I could just deliver a local page that doesn't exist but that doesn't seem right. I also want this to be usable on any server, and redirecting to "localhost" is also not an option ;-)
You could return -, which essentially means: 'no rewrite', but I don't know whether that's supported in a maps/[R] combination. Better may be to check with RewriteCond ${dbapp:$1} !^$ or something that it doesn't contain an empty string.