tags:

views:

507

answers:

4

I've got a fairly normal setup in which Apache proxies requests to a servlet running inside Tomcat over the AJP protocol.

We've run this setup on Apache 2.0.46/Tomcat 5.0.28 for ages without problems but have recently updated to Apache 2.2.3/Tomcat 5.5.

The problem is that we've noticed that intermittently (maybe one time in 3) Apache will somehow convert the "Content-Type" HTTP header of a page served by the servlet from "text/html" to "text/plain", which results in the browser displaying the HTML source instead of rendering it.

Has anyone seen this sort of behavior before and know what might be the cause? I suspect we're doing something bad in our servlet code that the old version of Tomcat/Apache was more forgiving of.

Update: I have confirmed that it's Apache changing the headers. If I browse directly to Tomcat the problem doesn't occur.

A: 

If you're seeing this problem intermittently, it's almost certain to be something in the servlet code rather than a misconfiguration of Tomcat or httpd. Do you have logging that you can turn on to print the contents of the HTTP headers ?

To isolate the problem a bit further, you could also try bypassing httpd and going direct to the Tomcat URLs for your pages.

I haven't seen this particular behaviour before myself, so sorry I can't be more specific.

gareth_bowles
A: 

By intermittent, do you mean that some pages exhibit this behaviour and others don't, or that there are pages that sometimes exhibit the behaviour and sometimes not?

Can you attach any logging to the AJP layer to log HTTP headers at that level, so you can verify whether it's Apache or Tomcat adding the bogus header?

DDaviesBrackett
The problem seems to affect any page in the app.
AndrewR
A: 

Are you proxying back to a cluster? Maybe one of the servers is configured wrong.

Swish
A: 

Ok. I figured it out, it was a bug in the servlet code:

We were doing something like this to write serialized Java objects as the result of HTTP requests:

DeflaterOutputStream dos = new DeflaterOutputStream(response.getOutputStream());
ObjectOutputStream oos = new ObjectOutputStream(dos);
response.setContentType("application/x-java-serialized-object");
oos.writeObject(someObject);

What seemed to be happening was that the DeflaterOutputStream and ObjectOutputStream would get garbage-collected three or four requests later when they were still attached to the response object's output stream and this would cause something to happen on the stream that confused Apache and caused it to rewrite the headers.

I replaced the above with:

ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
DeflaterOutputStream dos = new DeflaterOutputStream(byteStream);
oos = new ObjectOutputStream(dos);
response.setContentType("application/x-java-serialized-object");
oos.writeObject(someObject);
oos.flush();
dos.finish();
byteStream.writeTo(response.getOutputStream());

and the problem has gone away.

The following links seem to describe a similar problem:

AndrewR