Apache Mod_cache configuration with Tomcat and Max-age directives - apache

I have the following system configured:
Tomcat -> Apache
Now, I have some URLs on which I have Max-Age, LastModified and Etags set.
My expectation is when Client1 makes a call to the server, the page should get served from tomcat, but should get cached in the mod_cache module of Apache. So that when next client makes a call, the page is served from Apache and it doesnt have to hit the Tomcat server, if the page is still fresh. If the page isnt fresh, Apache should make a Conditional Get to validate the content it has.
Can someone tell me if there is any fundamental mistake in this thinking? It doesnt happen to work that way. In my case, when client2 makes a call, it goes straight to the Tomcat server(not even a Conditional Get).
Is my thinking incorrect or my Apache configuration incorrect?! Thanks

The "What can be cached" section of the docs has a good summary of factors - such as response codes, GET request, presence of Authorization header and so on - which permit caching.
Also, set the Apache LogLevel to debug in httpd.conf, and you will get a clear view of whether or not each request got cached. Check the error logs.
You should be able to trace through what is happening based on these two.

Related

does Apache do any DNS lookups on the Host header

I have received some results from a security scan that say that something is executing DNS A record look-ups on the URL in the Host header.
Having looked at the application code I can't see any such requests so I'm looking further up the stack.
I don't think Apache should be doing this but it's using mod_headers and mod_rewrite and maybe there is a configuration item in there that I have overlooked.
A long time ago, I came across an Apache httpd that was configured to do a reverse-lookup for IP-addresses before logging. While this was long denied, some requests were served quickly, while others took a long time (depending on the time required for the reverse lookup). And it became obvious once we looked at the logs (DNS names mixed with IP-addresses)
I don't see any reason why Headers and Rewrite would ever need to resolve any of the domains - they're purely working on strings/regexp.
Recommendation to figure out what's going on: Capture the traffic and figure out what domains/addresses are looked up when. With DNS still being largely unencrypted, this might be fairly easy, and point you to the smoking gun.

Domain URL masking

I am currently hosting the contents of a site with ProviderA. I have a domain registered with ProviderB. I want users to access the contents (www.providerA.com/sub/content) by visiting www.providerB.com. A domain forward is easy enough and works as intended, however, unless I embed the site in a frame (which is a big no-no), the actual URL reads www.providerA.com/sub/content despite the user inputting www.providerB.com.
I really need a solution for this. A domain masking without the use of a frame. I'm sure this has been done before. An .htaccess domain rewrite?
Your help would be hugely appreciated! I'm going nuts trying to find a solution.
For Apache
Usual way: setup mod_proxy. The apache on providerB becomes a client to providerA's apache. It gets the content and sends it back to the client.
But looks like you only have .htaccess. So no proxy, you need full configuration access for that.
So you cannot, see: How to set up proxy in .htaccess
If you have PHP on providerB
Setup a proxy written in PHP. All requests to providerB are intercepted by that PHP proxy. It gets the content from providerA and sends it back. So it does the same thing as the Apache module. However, depending on the quality of the implementation, it might fail on some requests, types, sizes, timeouts, ...
Search for "php proxy" on the web, you will see a couple available on GitHub and others. YMMV as to how difficult it is to setup, and the reliability.
No PHP but some other server side language
Obviously that could be done in another language, I checked PHP because that is what I use the most.
The best solution would be to transfer the content to providerB :-)

Premature end of script headers on one server but not another

I have two servers. They are both running the same code and are connected to the same database. But when I make a certain ajax call, one server works fine, and the other throws an Internal Server Error. Inside the Apache log of the internal service error server, it says 'Premature end of script headers'. This makes me think that there is some Apache error on one machine, but the Apache folder looks identical on both machines.
What sort of differences between servers would cause one to throw this error?
The error tells that you that no headers were output where they should be output. Typically it happens with a cgi script that fails for some reason and hence does not output anything, or outputs stuff before outputting the headers.
To debug it: Look in the apache error log. It will most likely tell you what went wrong.
To find the error_log: Look for the ErrorLog directive in the apache configuration file.
Swa66 etc have provided good answers but I thought that I would add a few more things to look into after you you reviewed the apache error logs which should give you the text that was returned where Apache was expecting a valid http header.
You mentioned that the servers are responding to Ajax queries and so it is possible that you are having some kind of CORS issues or issues relating to how Apache is configured to allow HTTP headers to be passed through to the CGI process.
It is not uncommon to include JWT or other auth headers as part of an ajax service and you may find that you need to add either a .htaccess file permitting these to flow through
Check your working server to see if the headers module is enabled ( - something like this in you httpd.conf - LoadModule headers_module libexec/apache2/mod_headers.so )
Also look for the .htaccess or domain specific configuration of the header related options. If need be, have a dig around relating to Apache CORS configuration and header related issues.
You may need some kinds of configuration similar to the following.
.htaccess
SetEnvIf Authorization .+ HTTP_AUTHORIZATION=$0
Header set Access-Control-Allow-Origin "*"
It is a little difficult to be certain of your issue without more specific diagnostics. Perhaps you could provide debugger details from your browser describing the Ajax/XHR requests including the headers etc and the relevant error log entries from apache. Assuming that you are using Perl/CGI perhaps snippets describing the CGI configuration from the config and any .htaccess files on the working and errant server.
You may also want to do a quick check of the permissions of the executables and try to run them from the command line.
It could be a very basic configuration option such as described at apache centos fails to serve images - premature end of script headers .. we really need a little more diagnostic detail to focus on possible causes.

Configure Access-Control-Allow-Origin for monit

I am trying to grab json data from monit and display it on a status page for management to see the current status of a handful of processes. This info would be displayed in Confluence running on the same machine but since Confluence (apache) and monit are running on different ports it is considered to be cross domain.
I know I can write a server side process to serve this data but that seems to be overkill and would actually take longer that it took to set monit up in the first place :)
The simplest solution is to configure monit's headers (Access-Control-Allow-Origin) to allow the other server. Does anyone know how to do this? I suspect there is a way since M/Monit would run into the same issue. I have tried some blind attempts on the "httpd... allow" lines but it complains about the syntax with x.x.x.x:port or using keyword "port" in that location.
ok... going to answer my own question (sort of).
First, I think I may have asked the question wrong. I don't deal with a lot of cross domain issues. Sorry about that.
But here is what I did to get to the monit info from the other servers: pretty simple using proxies in apache where the main server is:
ProxyPass /monit http://localhost:2812
ProxyPassReverse /monit http://mainserver/monit
ProxyPass /monit2 http://server2:2812
ProxyPassReverse /monit2 http://mainserver/monit2
I did this for each of the servers and tested that I can get to either the monit web interface or to the _status?format=json sub pages. I can now call them using ajax on our main web page.
This also has the benefit that I can lock down the monit access control to just the main server but have the info show on a more visible page. :)
I don't think you would need a proxy to just display monit's api or http info. It depends on how you have your network and dns configured. If you'd like to use only localhost, then that might be necessary. But, monit does have a facility to use global host ip access using allow directives in it's own config rc file

Apache is incorrectly converting jsp pages to "text/plain"

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.
Some webapps do not properly set mime types of content they serve, but still may work properly when served standalone because client applications like browsers are able to interpret the type of the content. But when served behind Apache, these apps will not behave correctly because Apache will provide a default type of text/plain.
A solution is to add a DefaultType None line to your apache virtual host for these web apps:
DefaultType None
http://httpd.apache.org/docs/2.2/mod/core.html#defaulttype
From my blog post:
http://patternbuffer.wordpress.com/2011/11/30/mime-type-issue-with-apache-mod_jk-and-mod_proxy-serving-plain-text/
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.
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?
Are you proxying back to a cluster? Maybe one of the servers is configured wrong.
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:
AJP Flush Packet causing text/plain
ASF Bugzilla – Bug 43478
I was also facing the same issue it got resolved.
If problem in only one folder then there is some servlet that is blocking the request/response and making a customize request/response to tomcat.
Tomcat 7.0.x