1+ package xdvrx1_serverProject ;
2+
3+ /*
4+ * This is where the request of a client
5+ * is being processed. When we say `client`,
6+ * it can be Google Chrome or any other browser.
7+ * This implements `Runnable` to be called in
8+ * `FileWebServer` class.
9+ */
10+
11+ import java .nio .file .Files ;
12+ import java .io .*;
13+ import java .net .*;
14+
15+ import java .util .logging .*;
16+
17+ public class ClientRequest implements Runnable {
18+
19+ FileNotFoundMessage message1 = new FileNotFoundMessage ();
20+ NotSupportedMessage message2 = new NotSupportedMessage ();
21+
22+ private String defaultPage = "index.html" ;
23+ private File rootDirectory ;
24+ private Socket connection ;
25+
26+ private final static Logger requestLogger =
27+ Logger .getLogger (ClientRequest .class .getCanonicalName ());
28+
29+ //the constructor
30+ public ClientRequest (File rootDirectory ,
31+ String defaultPage ,
32+ Socket connection ) {
33+
34+ //check if the given rootDirectory is a file
35+ //and will explicitly throw an exception
36+ if (rootDirectory .isFile ()) {
37+ throw new
38+ IllegalArgumentException ("rootDirectory must be"
39+ + "a directory, not a file" );
40+ }
41+
42+ //will try to get the canonical pathname
43+ //from the supplied `rootDirectory` argument
44+ try {
45+ rootDirectory = rootDirectory .getCanonicalFile ();
46+ } catch (IOException ex ) {
47+ requestLogger .log (Level .WARNING , "IOException" , ex );
48+ }
49+
50+ //constructors `rootDirectory` is assigned to
51+ //the successful `rootDirectory`
52+ this .rootDirectory = rootDirectory ;
53+
54+ if (defaultPage != null ) {
55+ this .defaultPage = defaultPage ;
56+ }
57+
58+ this .connection = connection ;
59+ }
60+
61+ @ Override
62+ public void run () {
63+
64+ try {
65+ //raw output stream,
66+ //in case it is not a text document
67+ //this will be used purely to pass
68+ ///the data as bytes
69+ OutputStream raw =
70+ new BufferedOutputStream (connection .getOutputStream ());
71+
72+ //for text files that uses the
73+ //underlying output stream
74+ Writer out =
75+ new OutputStreamWriter (raw );
76+
77+ //for reading the GET header from a browser
78+ Reader in =
79+ new
80+ InputStreamReader (new
81+ BufferedInputStream (connection
82+ .getInputStream ()),
83+ "US-ASCII" );
84+
85+ //the request line of a client
86+ StringBuilder requestLine = new StringBuilder ();
87+ while (true ) {
88+ int c = in .read ();
89+ if (c == '\r' || c == '\n' ) break ;
90+ requestLine .append ((char ) c );
91+ }
92+
93+ //just converted to string for further processing
94+ String requestLineToString = requestLine .toString ();
95+ requestLogger
96+ .info (connection
97+ .getRemoteSocketAddress () + " " + requestLineToString );
98+
99+ //`_keywords` are the words separated from the
100+ //request line,
101+ //`GET /data/ HTTP/1.1`
102+ String [] _keywords = requestLineToString .split ("\\ s+" );
103+ String method = _keywords [0 ];
104+ String http_version = "" ;
105+
106+ if (method .equals ("GET" )) {
107+ String fileName = _keywords [1 ];
108+
109+ //add manually the default page
110+ if (fileName .endsWith ("/" )) {
111+ fileName = fileName + defaultPage ;
112+ }
113+
114+ String contentType =
115+ URLConnection .getFileNameMap ().getContentTypeFor (fileName );
116+
117+ if (_keywords .length > 2 ) {
118+ http_version = _keywords [2 ];
119+ }
120+
121+ File actualFile =
122+ new File (rootDirectory ,
123+ fileName .substring (1 , fileName .length ()));
124+
125+ String root = rootDirectory .getPath ();
126+
127+ // restrict clients inside the document root
128+ if (actualFile .canRead ()
129+ && actualFile .getCanonicalPath ().startsWith (root )) {
130+
131+ byte [] _data = Files .readAllBytes (actualFile .toPath ());
132+
133+ if (http_version .startsWith ("HTTP/" )) {
134+ // send a MIME header
135+ ServerHeader
136+ .serverHeader (out ,
137+ "HTTP/1.0 200 OK" ,
138+ contentType ,
139+ _data .length );
140+ }
141+
142+ // still send the file;
143+ //and use the underlying stream
144+ //instead of the writer
145+ raw .write (_data );
146+ raw .flush ();
147+
148+ } else {
149+
150+ // file not found
151+ if (http_version .startsWith ("HTTP/" )) {
152+ // send a MIME header
153+ ServerHeader
154+ .serverHeader (out ,
155+ "HTTP/1.0 404 File Not Found" ,
156+ "text/html; charset=utf-8" ,
157+ message1 .body .length ());
158+ }
159+
160+ out .write (message1 .body );
161+ out .flush ();
162+ }
163+ } else {
164+ // method is not "GET"
165+ if (http_version .startsWith ("HTTP/" )) {
166+ // send a MIME header
167+ ServerHeader .serverHeader (out ,
168+ "HTTP/1.0 501 Not Implemented" ,
169+ "text/html; charset=utf-8" ,
170+ message2 .body .length ());
171+ }
172+
173+ out .write (message2 .body );
174+ out .flush ();
175+ }
176+ } catch (IOException ex ) {
177+ requestLogger
178+ .log (Level .WARNING , "Can't talk to: "
179+ + connection .getRemoteSocketAddress (), ex );
180+ } finally {
181+ try {
182+ connection .close ();
183+ } catch (IOException ex ) {
184+ requestLogger .log (Level .WARNING , "IO exception" , ex );
185+ }
186+ }
187+ }
188+
189+ }
0 commit comments