--#--
Who are these variables?
--#--
Where did these variables come from, and why are they
there? The environment variables you saw listed are there
because they were written into the CGI specification by
the National Center for Supercomputing Applications (NCSA)
at the University of Illinois at Urbana-Champaign.
NCSA, as you may well know, was the birthplace of the
Mosaic browser (grandaddy to both Netscape and Internet
Explorer) and the NCSA httpd server (daddy of Apache).
But where do they come from? Specifically, they come from
the server, which gleans them from information supplied by
the browser, information available in the Internet packets
it receives, and information the server knows about its own
environment.
Let's take a closer look. Fire up the Bounce
server covered elsewhere on this site. Run him on port 9000, and then
direct a browser to http://localhost:9000.
GET / HTTP/1.0
Connection: Keep-Alive
User-Agent: Mozilla/4.51 [en] (X11; I; Linux 2.2.5-15 i686)
Host: localhost:9000
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*
Accept-Encoding: gzip
Accept-Language: en
Accept-Charset: iso-8859-1,*,utf-8
Notice the header strings the browser sends to Bounce. The
environment variables you saw prefixed with HTTP_ are
all here as unadorned lines in the request header.
Now, create an HTML page with a link to Bounce.
Bouncer
Click on me
See how the browser now sends a
Referer: string in the header?
If you go against /cgi-bin/printenv.cgi, you'll see that translated to
HTTP_REFERER in the environment variables. Is this because the server is
looking for something called Referer? I think not.
For a laugh, try this. Remember Sneaky
Pete, our handrolled browser? Send him up against a /cgi-bin/printenv.cgi
script, with the following code in his request header.
public static void main(String[] args) {
String host = "localhost";
String url = "/cgi-bin/printenv.cgi";
try {
Socket socket = new Socket(host, 80);
InputStream response = socket.getInputStream();
PrintWriter agent =
new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
agent.println("GET " + url + " HTTP/1.0");
agent.println("Sea Monkeys: 1000");
agent.println();
agent.flush();
}
You'll get back HTTP_SEA_MONKEYS: 1000 Browsers could choose to send the
server anything in the world. They could also choose not to
send anything at all. The RFCs make statements about what a browser
should put in a header, but that's no guarantee.
Sure, the major browsers are interested in promoting a predictable
environment for browsers and servers to operate in. So, for the most
part, they stick to the standards. But they ocassionally diverge.
And then there are the renegades, hackers and crackers and worse.
Who knows what they put into the request header, or leave out? (You
just sneaked Sea Monkey into Pete's request header, didn't you?)