Add HTTP Headers in Apache Response

This can be used to for several reasons:

  1. To add headers to modify the behavior of a specific ‘misbehaving’ browser or client.
  2. To replace headers that you don’t want leaked to the Internet.
  3. To add monitoring information to your server responses.

Changes can be accomplished in the Apache2 ‘httpd.conf’ file.

  1. Verify that the module is not disabled or commented out:

    LoadModule headers_module modules/

  2. To add some common metrics:

    <IfModule headers_module>
    Header append MyHeader “%D %t”

  3. To Hide the HTTP Server header that you send in your responses (often done for security through obscurity):
    <IfModule headers_module>
    Header unset Server
  4. You could also replace the Server Header like this:

    <IfModule headers_module>
    Header set Server “ScottServer 1.0”


Configuring Apache webserver for browser caching of web content…

This is a HUGE topic, I’ve outlined some simple steps below as well as my initial configuration for you to start with…

NOTE: this is for simple ‘static’ content such as images, additional work is required for dynamic (program generated) content, such as that generated in PHP.

1. In ‘httpd.conf’ make sure the following line is uncommented.

LoadModule expires_module modules/

2.  In ‘httpd.conf’ add the following:

ExpiresActive On
### Expire images 1 day from when they’re accessed
ExpiresByType application/java-archive “access plus 1 day”
ExpiresByType image/gif “access plus 1 day”
ExpiresByType image/png “access plus 1 day”
ExpiresByType image/jpg “access plus 1 day”
ExpiresByType image/jpeg “access plus 1 day”
ExpiresByType image/x-icon “access plus 1 day”
ExpiresByType text/css “access plus 1 day”
ExpiresByType text/javascript “access plus 1 day”
ExpiresByType text/xml “access plus 1 day”
ExpiresByType application/xml “access plus 1 day”
ExpiresByType text/plain “access plus 1 month”

3. (Optional) Set default expiry of content in ‘httpd.conf’:

### Expire everything else 1 day from when it’s last modified
ExpiresDefault “modified plus 1 day”

NOTE: These we’re my original settings, you may want to add attitional MIME type and expiry configurations particular to your web content.


Open Source Operating Systems

I’ve posted a lot of information about the common ‘free’ open-source software that I routinely use, however… I just realized that I missed one of the most important applications you use, the Operating System itself.

While my “day job” relegates me to use Windows products for much of my work, I do a lot of additional work at home and for friends.

Currently I use and highly recommend Ubuntu Linux for most users, it’s got most of the usability features of Microsofr Windows and Apple OS/X, but without all of the additional baggage. It’s updated regularly, with new releases every 6 months and software patches made available almost daily. Updates are as non-intrusive as the Windows Update process, and only a very few ever require a reboot.

To quiet the other Linux users out there, I’ve used a lot of Linux ‘flavors’ in the past… each has had it’s place and may do so again…. this is my opinion for the moment and will likely change again in a few years. 🙂

Here’s the list:


Javascript ‘Response Time’ measurement (latency)

Here’s another ‘fun’ trick. When you build complex web applications, performance metrics start to become an issue. Unfortunately, web tools for this are not typically available within the browser itself and ‘testers’ often rely of such non-technical solutions as stop-watch timing. Not only is this time consuming, but it is nearly impossible to reproduce as the ‘time’ includes the hand-eye coordination of the person using the watch.

In defense of the software itself, there are several Mozilla add-ons to help with this issue, but my solution is in your application code and as such can be enhanced to provide notification or logging with some additional work.

If you’ve ever used a 3270 Emulator (Mainframe “Green Screen”) you’re probably familiar with seeing this data as most 3270 clients expose it somewhere on the screen.

The trouble here is that there is no good API to do this, and no javascript variables are persisted across page loads. (cookies would be overkill). What we’re left with is the browser window-name itself, while it’s normally used when naming ‘popup’ windows and is not visible directly to the user, it provides a ‘safe’ place to store this transient data between pages.
When leaving a page we store the current time, to be sure that we can find the correct data in the window name we use unique prefix and suffix values and add the current name so that it can be restored later.

When the new page is loaded we have to compare the current time with the stored time, then we have to be sure to restore the window ‘name’ as can’t be sure about what other reason it may be named, and we don’t want to interfere.

NOTE: If you also have access to the server code (PHP or Servlet for example) or can wrap calls to external systems like databases, you can make this much more granular by including those times. In that case you could report total time, extract database time, then extract servlet time, then ‘deduce’ network latency itself! This goes a long way when troubleshooting vague user experiences when they indicate that the “site is slow” as you can now pinpoint the problem area(s) to focus on.

WARNING: For Mozilla/Firefox the default security settings prevent JavaScript from modifying the ‘window status’ used in the example code. In a real implementation you might consider using DHTML to insert the output somewhere else. Otherwise changing Mozilla Firefox 2.x’s settings is found at Tools, Options, Content Tab, Advanced JavaScript settings.

var build=’GiantGeek Example’; // you could put build label information here 🙂
var PRE=”MMSpre”;
var SUF=”MMSsuf”;

function xload(){
var tim=grvGetDuration();
build=build + tim;
function xclose(){
function xlinkObj(obj,url){ // this is for all valid links
window.location.replace(uniqueUrl(url)); // ‘replace’ has side-effect of ‘restricting’ back-button, or ‘location’
return false;
function grvMillis(){
return new Date().getTime();
function grvSetTimeclean(){
var dummy=grvGetTimeclean(); // get any remainder (dupes?)
var x=grvGetName() + grvMms();
function grvMms(){
return PRE + grvMillis() + SUF;
function grvGetDuration(){
var rc=”;
var old=grvGetTimeclean();
rc=” [” + (grvMillis() – old)/1000 + “]”;
return rc;
function grvGetTimeclean(){
var x=grvGetName();
var pre = x.indexOf(PRE);
var suf = x.indexOf(SUF);
var rc=”;
if((pre >= 0) && (suf > pre)){
// get the garbage in the name (around mms)
var p=x.substring(0,pre);
//var s = x.substr(suf+SUF.length);
//assemble new name (without mms)!
return rc;
function grvGetName(){
var rc =;
return rc;
function grvSetName(x){;
function grvWindowStatus(txt){
function uniqueUrl(x){ // this adds a timestamp to URLs
var mms = grvMillis();
var delim = “?”;
if(x.indexOf(“?”) >=0) { delim = “&”; }
return x + delim + ‘time=’ + mms;
<body onunload=”xclose();” onload=”xload();”>

Private Caching/Relay DNS Server

Since I’ve run a few small websites (like this one) out of my home for years, I’ve found it useful to run a DNS server inside of my firewall. Not only does this make it easier to maintain the websites, but it allows me to lock down security and increase performance of many of my applications.

I run a the following services that use DNS:

  • Apache JAMES – mail server that does lookups to send email and filter inbound SPAM.
  • Analog – web server log analysis.
  • Apache HTTPD – web server, used to host websites, private domains used for internal purposes.

To make things more efficient, I currently have my DNS setup to forward all requests to OpenDNS, allowing for ‘adult’ website filters and analysis of DNS activity.

Some open-source/free DNS servers that I recommend:


Unreal Tournament 2004

I’m not much of a game player, but a group of guys from the office decided that it would be fun to blow off some steam by fragging each other once in a while. I’ve got a dedicated server setup, but for obvious reasons it’s password protected. If you are a regular reader of this blog and are interesting in joining us on occasion, please drop me an email or reply to this post. Even better… see me IRL.

Happy fragging!

Installing Perl CGI on Apache (for Windows)

Installing Perl on a Win32 installation of Apache is trivial. Just a few short years ago (roughly the year 2000) most commercial website still ran large amounts of Perl code. Several open-source projects like BugZilla still rely on this powerful scripting language.

Here’s a few simple steps and advice to consider when the need comes to add this feature to your installation.

  1. Download Perl for Win32 – ActiveState Perl is the standard distribution to use, and installation is a snap.URL = Get the MSI file version as it’s executable (the AS version is a ZIP file for manual installs)

    b) The default path it chooses is “C:\Perl”, I advise that you use “c:\usr” instead as it makes it easier to port programs to and from UNIX/LINUX.

    c) The MSI installer takes care of the PATH file settings, so you should have no other work for installation.

  2. Modify the Apache httpd.conf file to enable (uncomment or add the following lines).

    AddHandler cgi-script .cgi
    AddHandler cgi-script .pl

  3. Restart Windows to ensure that the new configuration is available to the operating system.
  4. Test your install…a) Create a new file on the server named /cgi-bin/ with the following content:

    print “Content-type:text/html\n\n”;
    print “hello world”;

    b) Start (or restart) the Apache service.

    c) Access the file in the browser, example:

    URL = http://localhost/cgi-bin/

    d) If everything works, you should see the words “hello world”, otherwise, if you see the source code or ‘500 Server Error’ then the config has a problem.

Happy Scripting.


I’ve used EveryDNS (free service) for years to host my DNS services.    Recently I found that they now offer public DNS service for lookups as OpenDNS.   While I still run my own private DNS server for caching and various private addresses.  I now do a simple forward lookup to their servers to gain the extra services they provide… notably Phishing  and typo protection.

Setup is very simple for most users, and even a non-technical person should have no problems following their installation instructions for a single computer/device or an entire network.
Happy networking!!!

WAMP Servers

I often find myself administering WAMP (Windows, Apache, PHP/Perl/Python, mySQL) servers…. usually this occurs because it is better ‘supported’ (or perhaps ‘tolerated’) configuration in a corporate alternative to the more common LAMP (Linux… etc.) variety. This gives you the benefit of a centrally controlled operating system while maintaining a mostly open source server environment. Albeit with Microsoft’s poor security record, you’ll be patching it a LOT!

Many common distributions exist… here’s some helpful resources with downloads:

If you are a Java shop, you might also consider the following…

Configuration of each of these is a topic in it’s own right. If you need a shortcut to development, you may want to check out this!

Good luck!!!

Proxy Auto-config

There comes a need for many organizations (or individuals) to establish proxy servers on their network. This is usually done for reasons of security or network topology. While the use of proxy servers simpifies some aspects of networking, it comes at the cost of maintaining the browser configuration of every network device (usually browsers). Netscape provided a mechanism to automate much of this problem by allowing the browser to retrieve the proxy configuration from a centrally managed server.

The proxy autoconfig file is written in JavaScript, it should be a separate file that has the proper filename extension and MIME type when provided from a webserver.

The file must define the function:

function FindProxyForURL(url, host)




4. ApacheHTTP config.

Add the following to the httpd.conf file:

Redirect permanent /wpad.dat {yourdomain}/proxy.pac
AddType application/x-ns-proxy-autoconfig .pac


/* 'proxy.pac' - This is the main function called by any browser */
function FindProxyForURL(url, host)

if (isPlainHostName(host) || // No Proxy for Non FQDN names
shExpMatch(host, “*.localnet”) || // No Proxy for internal network
shExpMatch(host, “”) || // No Proxy for LocalHost
shExpMatch(host, “localhost”) || // No Proxy for LocalHost
shExpMatch(host, “mailhost”) || // No Proxy for MailHost
dnsDomainIs(host, “”) || // No Proxy
return “DIRECT”;

else {

} //End else

} // End function FindProxyForUrl

NOTE: Also see my ‘WPAD’ blog entry.