//
// example of java.net.* classes.
//
// adapted from example in ch. 11 of _Exploring Java_, Niemeyer & Peck.
//
// version 1: no security manager. (but program responds to requests
// just by confirming the requested file's existence and size, and
// is restricted to those files to which server program has read
// access.)
//
import java.net.* ;
import java.io.* ;
import java.util.* ;
//
// ---- main -----------------------------------------------------------
//
// command-line argument is port number.
//
// instructions for testing:
//
// (1) start the TinyHttpd1 server:
// java TinyHttpd1 nnnn
// (nnnn is any port number you choose, higher than 1024)
// suppose mymachine.org is the name of the machine on which
// you've done this, and nnnn = 1234.
//
// (2) point a Web browser at it, via URLs like:
// http://mymachine.org:1234/filename
//
// filename will be interpreted relative to the directory *in
// which you started TinyHttpd1*. to specify an
// absolute pathname, include an extra "/", e.g.,
// http://mymachine.org:1234//toplevel/midlevel/filename.
//
// if you don't know the name of the machine on which you're
// running, you can use its IP address instead. for
// a Windows machine, you may be able to get its IP address
// by typing "winipcfg" at a DOS prompt.
//
// when done, stop the server with control-C.
//
// these instructions have been tested on Unix and Windows systems at
// UF, and on Linux systems at Trinity.
//
public class TinyHttpd1 {
public static void main(String[] args)
throws IOException {
if (args.length < 1) {
System.out.println("Argument is portnum") ;
System.exit(-1) ;
}
// create server socket to accept client requests.
ServerSocket ss =
new ServerSocket(Integer.parseInt(args[0])) ;
// accept client requests, creating a new thread for
// each.
while (true) {
new TinyHttpd1Connection(ss.accept()).start() ;
}
}
}
//
// a TinyHttpd1Connection object is a thread that serves a
// client request (of the form GET /filename .. options ..).
// "filename" (without the leading slash) is assumed to be a file
// in the server's directory.
// it sends back to the client:
// error message for badly formed request or file not found.
// some info about file otherwise.
//
class TinyHttpd1Connection extends Thread {
Socket client ;
PrintWriter pout ;
TinyHttpd1Connection(Socket client) throws SocketException {
this.client = client ;
setPriority(NORM_PRIORITY - 1) ;
}
public void run() {
try {
// create in, out streams using standard
// encoding for HTTP.
BufferedReader in = new BufferedReader(
new InputStreamReader(
client.getInputStream(),
"8859_1")) ;
pout = new PrintWriter(
new OutputStreamWriter(
client.getOutputStream(),
"8859_1"),
true) ;
// read and echo request.
String request = in.readLine() ;
System.out.println("Request: " + request) ;
// parse request.
StringTokenizer st =
new StringTokenizer(request) ;
if ((st.countTokens() >= 2) &&
st.nextToken().equals("GET") ) {
serviceRequest(st.nextToken()) ;
}
else {
pout.println("400 Bad Request") ;
}
client.close() ;
} catch (IOException e) {
System.out.println("I/O error " + e) ;
}
}
// processes request (filename).
private void serviceRequest(String filereq) {
// strip off leading "/".
if (filereq.startsWith("/"))
filereq = filereq.substring(1) ;
// append "index.html" if name ends with "/".
if (filereq.endsWith("/") || filereq.equals(""))
filereq = filereq + "index.html" ;
// try to return info about file.
File f = new File(filereq) ;
if (f.exists()) {
if (f.isDirectory()) {
pout.println("Directory " + filereq +
" found
") ;
if (f.canRead())
pout.println("Contains " +
f.list().length +
" files or subdirectories
") ;
else
pout.println("Not readable
") ;
}
else {
pout.println("File " + filereq +
" found
") ;
pout.println("Size = " + f.length() +
" bytes
") ;
}
}
else
pout.println("404 File Not Found") ;
}
}