HTTP Response Headers fixup
HTTP Response Headers fixup
am 31.12.2008 12:33:12 von aw
Hi.
I have a peculiar problem, and need a peculiar solution.
In an Apache 2.2.3, mod_jk, Tomcat 5.5.x, mod_perl2, perl 5.8.8, Linux
environment, some links are being re-directed by Apache via mod_jk, to a
back-end Tomcat server, and a webapp running in that server.
For reasons that are off-topic and obscure, that webapp generates html
pages that are really encoded in iso-8859-2, but with a Content-Type
response header that says they are iso-8859-1. It's like that, and I
cannot change this at the webapp or Tomcat level, not even with a
servlet filter.
So I need to modify the Content-Type response header, after-the-fact
(meaning when the response from Tomcat has been channeled back to Apache
via mod_jk).
My first inspiration was to do it using mod_headers.
But this does not work for some reason. I have been told on either the
Apache or Tomcat forum, that it was because Apache or mod_jk does
something internally, to prevent the response headers generated by
Tomcat, to be modifiable by Apache later on.
I do not really know if that is true, but it matches the symptoms that I
am seeing : a custom HTTP header that I *add* to the response after
mod_jk shows up properly at browser level, but it conpletely ignores my
attempts at deleting/editing/replacing the Content-Type header for the
same response.
Then I found Apache2::Filter::HTTPHeadersFixup, which seems to be almost
exactly what I am looking for.
Except that I have a doubt :
HTTPHeadersFixup is a connection filter, I guess by necessity for that
kind of thing. Which means that it affects all requests that go through
that VHost. However, only a small fraction of these requests (the ones
that are re-directed to that rogue Tomcat application) should have their
response Content-Type modified, and not all requests.
So my question is, rather generally, what would be the best way to
implement what I need, either with HTTPHeadersFixup or without it ?
Here is a snippet of the configuration I have at the moment, including
what I tried with mod_headers (but which does not work) :
(lines with ### prefix are my comments to explain what it does/should do)
Start :
### set the is-jk variable only for requests that will be re-directed to
the rogue Tomcat application
SetEnvIf REQUEST_URI "/servlet\.[^\.]+$" is-jk
### if the above var is set, then try modifying the mod_jk response
header after-the-fact, at VHost level
Header always set Content-Type: "text/html; charset=ISO-8859-2" env=is-jk
### just to check the above, also add a custom header to the response,
under the same conditions
Header always set Test-Header: "VHost level" env=is-jk
### the following Location is where the mod_jk redirect really happens
(the setHandler plays the same role as a JkMount directive)
SetHandler jakarta-servlet
### try the same as before, but within the specific Location scope
Header always set Content-Type: "text/html; charset=ISO-8859-2"
Header always set Test-Header: "Location level"
:End
The result of the above, is that the custom header "Test-Header" gets
indeed added to the appropriate responses, at the "Location" level (the
Location directive replaces the one generated by the generic one).
But, the Content-Type header obstinately stays at what the rogue webapp
set it, which is "Content-Type: text/html; charset=ISO-8859-1" (instead
of -2 at the end).
One of my questions is thus : assuming I keep adding this custom header
"Test-Header" via mod_headers, will it be visible by the
HTTPHeadersFixup subclass I create and configure ? if yes, I could make
a simple test in my subclass to detect if this request is indeed one
that needs to be modified. Or is there another/better/simpler way to
resolve my problem ?
And, best wishes to all for tomorrow and on.
Re: HTTP Response Headers fixup
am 31.12.2008 17:21:49 von David Ihnen
André Warnier wrote:
>
> One of my questions is thus : assuming I keep adding this custom
> header "Test-Header" via mod_headers, will it be visible by the
> HTTPHeadersFixup subclass I create and configure ?
Its an output connection filter, so I can't imagine it wouldn't work as
you expect.
> if yes, I could make a simple test in my subclass to detect if this
> request is indeed one that needs to be modified.
If the filter configuration in the is insufficient you mean?
You certainly can inspect and react.
> Or is there another/better/simpler way to resolve my problem ?
http://perl.apache.org/docs/2.0/user/handlers/filters.html#C _PerlOutputFilterHandler_
You can also use output filter handler stage... just look for the header
in the brigade and insert your own header instead.
Though that sounds more complicated than the ready-made header fixup
handler. :)
David
Re: HTTP Response Headers fixup
am 01.01.2009 13:58:58 von aw
As a complement to this thread, I would like to reproduce an answer
received on the Tomcat list, from Rainer Jung, the developer/maintainer
of the mod_jk module.
It explains why I wasn't (and can't) get any success doing what I wanted
with either mod_headers or a mod_perl connection output filter (which I
tried).
Rainer Jung :
Apache 2 has hooks for modules, but also filters. The hooks allow to
interact with request processing at certain stages and the modules
decide, whether they allow other modules to be called in the same hook.
mod_headers is a filter, which allows to manipulate requests and
responses much like servlet filters during the reading and writing of
request resp. response. Thus you can use mod_headers to change headers
after they are returned by mod_jk.
Unfortunately the Content-Type header is a different beast. Inside
Apache it is not only a response header, but a more complex data type.
You can set a different Content-Type header with mod_headers, but since
the internal structure remains unchanged it will be overwritten again by
Apache.
As a result I see no way to change an existing character set in a
Content-Type header.
> I have tried changing the Content-Type header in a servlet filter under
> Tomcat. However, that also has the side-effect that the servlet then,
> for its response, really uses the new character encoding specified in
> the header, to produce its response.
> That is not what I want here, because the problem is that the servlet
> response is already correct (in the iso-8859-2 encoding), it is just
> that the Content-Type header is incorrect and does not match the real
> charset of the response. The underlying reason for all that stuff is
> obscure and OT here, but that is really what happens.
See javax.servlet.ServletResponseWrapper. A filter can replace request
and/or response with a custom wrapper object. Whenever the servlet then
calls a method of the request or response object, your custom object is
called. Your custom response wrapper extends the standard one, which
itself lets all methods call through to the wrapped response. You can
then implement individual methods in a different way. You could for
instance overwrite setCharacterEncoding(java.lang.String charset) to set
something else, then demanded by the caller (e.g. iso-8859-2 instead of
iso-8859-1), and getCharacterEncoding() to return something different,
from what you actually set.
The filter can inspect e.g. the URL to decide, whether it should wrap
the response or not.
This mechanism can be used without any changes to the existing webapp
code, you only need to add your filter and wrapper to the webapp, and of
course add the filter to web.xml.
Regards,
Rainer
Re: HTTP Response Headers fixup
am 01.01.2009 14:32:48 von torsten.foertsch
On Thu 01 Jan 2009, André Warnier wrote:
> Unfortunately the Content-Type header is a different beast. Inside
> Apache it is not only a response header, but a more complex data
> type. You can set a different Content-Type header with mod_headers,
> but since the internal structure remains unchanged it will be
> overwritten again by Apache.
>
> As a result I see no way to change an existing character set in a
> Content-Type header.
Try to create a request output filter that sets $r->content_type,=20
removes itself and returns DECLINED.
Torsten
=2D-=20
Need professional mod_perl support?
Just hire me: torsten.foertsch@gmx.net
Re: HTTP Response Headers fixup
am 01.01.2009 14:41:05 von aw
Torsten Foertsch wrote:
[...]
>
> Try to create
- a request output filter
that I can do
- that sets $r->content_type,
that sounds easy
- removes itself
that, I'm not quite sure how to go about it
- and returns DECLINED.
that is also easy
But thanks anyway. If that works, it would be a lot easier than the
response wrapper under Tomcat, or than fixing that damn servlet.
Re: HTTP Response Headers fixup
am 01.01.2009 21:26:13 von aw
Torsten Foertsch wrote:
> On Thu 01 Jan 2009, André Warnier wrote:
>> Unfortunately the Content-Type header is a different beast. Inside
>> Apache it is not only a response header, but a more complex data
>> type. You can set a different Content-Type header with mod_headers,
>> but since the internal structure remains unchanged it will be
>> overwritten again by Apache.
>>
>> As a result I see no way to change an existing character set in a
>> Content-Type header.
>
> Try to create a request output filter that sets $r->content_type,
> removes itself and returns DECLINED.
>
Torsten, you're the greatest.
It works perfectly, even without having the filter remove itself (which
I did not know how to do).
Here is the minimal filter :
package AM::FixupContentType;
# Fixes bad servlet-generated Content-Type header, when used in
iso-latin-2 environment.
# Idea from Torsten Foetsch.
$AM::FixupContentType::VERSION = '0.01';
use strict;
use warnings FATAL => 'all';
use mod_perl2 2.000001;
use base qw(Apache2::Filter);
use Apache2::Const ();
sub handler : FilterRequestHandler {
my ($f, $bb) = @_;
$f->r->content_type("text/html; charset=ISO-8859-2");
return Apache2::Const::DECLINED;
}
1;
Re: HTTP Response Headers fixup
am 02.01.2009 20:45:10 von torsten.foertsch
On Thu 01 Jan 2009, André Warnier wrote:
> It works perfectly, even without having the filter remove itself
> (which I did not know how to do).
http://perl.apache.org/docs/2.0/api/Apache2/Filter.html#C_re move_
Torsten
=2D-=20
Need professional mod_perl support?
Just hire me: torsten.foertsch@gmx.net