Beispiel: HTTP-Server mit CGI

class HttpHandler

import java.net.Socket;
import java.net.InetAddress;
import java.io.*;
import sun.servlet.http.HttpDate;

public class HttpHandler extends Thread
{
 HttpServer Server; // Der Server-Thread
 Socket Connect;  // Die Socket der Verbindung
 String Method;
 String Filename, UnTrans; // Request-URI, absolut und relativ
 String Query = "";   // Query-String
 String CT;     // Content-Type
 String Version = "";  // HTTP-Version
 
// Konstruktor
 public HttpHandler(HttpServer server, Socket connect)
 {
  Server = server;
  Connect = connect;
 }

// Verarbeiten der Requests
 public void run()
 {
  try
  {
   BufferedReader br = new BufferedReader(
    new InputStreamReader(Connect.getInputStream()));
// erste Zeile lesen; z.B. "GET /hallo.html HTTP/1.0"
   String get = br.readLine();
   java.util.StringTokenizer st = new java.util.StringTokenizer(get);
   Method = st.nextToken();
   UnTrans = st.nextToken();
   if (UnTrans.indexOf("?") != -1)
   {
    Query = UnTrans.substring(UnTrans.indexOf("?")+1,UnTrans.length());
    UnTrans = UnTrans.substring(0,UnTrans.indexOf("?"));
   }
   Filename = Server.Translate(UnTrans);
   CT = Server.GuessContentType(Filename); // Content-Type
   if (st.hasMoreTokens())
    Version = st.nextToken();
   if (Server.IsCgi(Filename))
    HandleCgi(br);
   else
    SendFile();
  }
  catch (IOException e)
  {
   System.err.println("Unbekannter Fehler: " + e);
  }
  System.out.println("Anfrage um " + new HttpDate(
    HttpDate.getCurrentTime()));
 }
 
 void SendFile() throws IOException
 {
// restliche Sendung ignorieren
  Connect.getInputStream().skip(Connect.getInputStream().available());
  PrintStream os = new PrintStream(Connect.getOutputStream());
  try
  {
// die gefragte Datei lesen
   File file = new File(Filename);
   FileInputStream fis = new FileInputStream(Filename);
   int length = (int)file.length();
   byte[] data = new byte[length];
   fis.read(data);
   fis.close();
// geg. Status-Zeile und Header senden
   if (Version.startsWith("HTTP/1"))
   {
    os.print("HTTP/1.0 200 OK\r\n");
    os.print("Date: " +
        new HttpDate(HttpDate.getCurrentTime()) + "\r\n");
    os.print("Content-length: " + length + "\r\n");
    os.print("Content-type: " + CT + "\r\n\r\n");
   }
// geg. Datei senden
   if (! Method.equals("HEAD"))
    os.write(data);
   Connect.close();
  }
  catch (IOException e)
  {
// geg. File Not Found-Meldung senden
// geg. Status-Zeile und Header senden
   if (Version.startsWith("HTTP/1"))
   {
    os.print("HTTP/1.0 404 File Not Found\r\n");
    os.print("Content-type: text/html\r\n\r\n");
   }
   os.print("<HTML><HEAD><TITLE>File Not Found</TITLE></HEAD>"
    + "<BODY><H1>HTTP Error 404: File Not Found</H1></BODY></HTML>");
   Connect.close();
   System.err.println("Datei nicht gefunden: " + Filename);
  }
 }
 
 void HandleCgi(BufferedReader br) throws IOException
 {
// Einlesen des Header, insbesondere Content-length
// Eigentlich gehoeren diese Daten zu den CGI-Umgebungs-Variablen
  int inlength = 0;
  String get;
  while(br.ready())
  {
   get = br.readLine();
   if (get.toLowerCase().startsWith("content-length"))
   {
    inlength = Integer.parseInt(get.substring(
     get.indexOf(" ")+1, get.length()));
   }
   if (get.trim().equals(""))
    break;
  }
  try
  {
// Umgebungs-Variablen setzen
   String env[] = new String[18];
   InetAddress addr = Connect.getInetAddress();
   env[0]= "AUTH_TYPE=";
   env[1]= "CONTENT_LENGTH=" + inlength;
   env[2]= "CONTENT_TYPE=";
   env[3]= "GATEWAY_INTERFACE=";
   env[4]= "PATH_INFO=" + UnTrans;
   env[5]= "PATH_TRANSLATED=" + Filename;
   env[6]= "QUERY_STRING="  + Query;
   env[7]= "REMOTE_ADDR=" + addr.getHostAddress();
   env[8]= "REMOTE_HOST=" + addr.getHostName();
   env[9]= "REMOTE_USER=";
   env[10]= "REQUEST_METHOD=" + Method;
   env[11]= "SCRIPT_NAME=" + UnTrans;
   env[12]="SERVER_NAME=" +
    Connect.getLocalAddress().getHostName().toLowerCase();
   env[13]= "SERVER_PORT=" + Connect.getLocalPort();
   if (Version.startsWith("HTTP/1"))
    env[14]= "SERVER_PROTOCOL=HTTP/1.0";
   else
    env[14]= "SERVER_PROTOCOL=HTTP/0.9";
   env[15]= "SERVER_SOFTWARE=CgiHttp/1.0";
   env[16]= "HTTP_ACCEPT=";
   env[17]= "HTTP_USER_AGENT=";
// Cgi-Interpreter aufrufen
   Process proc = Server.CallCgi(Filename, env);
// Streams
   OutputStream cgiout = proc.getOutputStream();
   InputStream cgiin = proc.getInputStream();
   BufferedReader cgibr = new BufferedReader(
    new InputStreamReader(cgiin));
   InputStream in = Connect.getInputStream();
   OutputStream out = Connect.getOutputStream();
   PrintStream os = new PrintStream(Connect.getOutputStream());
// geg. Input an CGI weitergeben
   for (int i = 0; i < inlength; i++)
    cgiout.write(in.read());
// geg. Status-Zeile
   if (Version.startsWith("HTTP/1"))
   {
    os.print("HTTP/1.0 200 OK\r\n\r\n");
   }
// Output senden
   boolean finished = false;
   while (!finished)
   { // bis der CGI-Interpreter fertig ist
    try
    {
     proc.exitValue(); // Exception, wenn nicht fertig
     finished = true;
    }
    catch(IllegalThreadStateException e) {}
    if ((get = cgibr.readLine()) != null)
     os.print(get + "\r\n");
    // die zeilenweise Weitergabe hat ausserdem den Vorteil,
    // dass die Zeilenenden immer korrekt sind
   }
   Connect.close();
    // der Server muss schliessen, da Content-length fehlt
  }
  catch (Exception e)
  {
   System.err.println("Cgi-Fehler: " + e);
  }
 }
}