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);
}
}
}