11
11
import java .nio .file .Files ;
12
12
import java .io .*;
13
13
import java .net .*;
14
-
15
14
import java .util .logging .*;
16
15
17
16
public class ClientRequest implements Runnable {
@@ -56,16 +55,21 @@ public ClientRequest(File rootDirectory,
56
55
}
57
56
58
57
this .connection = connection ;
58
+
59
59
}
60
60
61
61
@ Override
62
62
public void run () {
63
63
64
64
try {
65
+ //remember, once the connection is established
66
+ //the server will use the Socket to pass
67
+ //data back and forth
68
+
65
69
//raw output stream,
66
70
//in case it is not a text document
67
71
//this will be used purely to pass
68
- /// the data as bytes
72
+ //the data as bytes
69
73
OutputStream raw =
70
74
new BufferedOutputStream (connection .getOutputStream ());
71
75
@@ -74,48 +78,86 @@ public void run() {
74
78
Writer out =
75
79
new OutputStreamWriter (raw );
76
80
81
+ //needed to add new line correctly
82
+ //for different platforms
83
+ BufferedWriter bufferedOut =
84
+ new BufferedWriter (out );
85
+
86
+ BufferedInputStream bis =
87
+ new BufferedInputStream (connection .getInputStream ());
88
+
77
89
//for reading the GET header from a browser
78
90
Reader in =
79
91
new
80
- InputStreamReader (new
81
- BufferedInputStream (connection
82
- .getInputStream ()),
83
- "US-ASCII" );
92
+ InputStreamReader (bis , "US-ASCII" );
84
93
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 );
94
+ //the request send by a client
95
+ //take note, this can be loaded into a data structure
96
+ //instead of using StringBuffer to generate string
97
+ //but, it's up to you, for demonstration
98
+ //I will just use the StringBuffer to build
99
+ //the string object
100
+ StringBuffer userRequest = new StringBuffer ();
101
+
102
+ //this will be the basis to get
103
+ //all the bytes from the stream
104
+ int bufferSize = bis .available ();
105
+
106
+ while (true ) {
107
+ if (userRequest .length () > bufferSize -1 ) {
108
+ //for performance, always shutdown
109
+ //after breaking from this loop
110
+ connection .shutdownInput ();
111
+ break ;
112
+ }
113
+
114
+ //read() of Reader is actually a blocking
115
+ //method, and without proper algorithm
116
+ //this will hang the entire program
117
+ int c = in .read ();
118
+ userRequest .append ((char ) c );
119
+
120
+ //ignore the line endings,
121
+ //the Reader will interpret this as end of buffer
122
+ //we need to read the entire content of the buffer
123
+ if (c == '\n' || c == '\r' || c == 1 ) continue ;
91
124
}
92
125
93
- //just converted to string for further processing
94
- String requestLineToString = requestLine .toString ();
126
+ //build a string object from StringBuffer
127
+ String userRequestToString = userRequest .toString ();
128
+
129
+ //get the first line through this index
130
+ int indexOfFirst = userRequestToString .indexOf ("\r \n " );
131
+ String firstLine = userRequestToString
132
+ .substring (0 ,indexOfFirst );
133
+
134
+ //express it in the logger, mostly for debugging purposes
95
135
requestLogger
96
136
.info (connection
97
- .getRemoteSocketAddress () + " " + requestLineToString );
137
+ .getRemoteSocketAddress () + " " + firstLine );
98
138
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 ];
139
+ //`token` are the words separated from the request line,
140
+ //for example, `GET /data/ HTTP/1.1`
141
+ String [] token = firstLine .split ("\\ s+" );
142
+ //0 index tells the method
143
+ String method = token [0 ];
144
+ //null at first
104
145
String http_version = "" ;
105
146
106
147
if (method .equals ("GET" )) {
107
- String fileName = _keywords [1 ];
148
+ String fileName = token [1 ];
108
149
109
150
//add manually the default page
110
151
if (fileName .endsWith ("/" )) {
111
152
fileName = fileName + defaultPage ;
112
153
}
113
154
155
+ //get the content type for proper encoding of data
114
156
String contentType =
115
157
URLConnection .getFileNameMap ().getContentTypeFor (fileName );
116
158
117
- if (_keywords .length > 2 ) {
118
- http_version = _keywords [2 ];
159
+ if (token .length > 2 ) {
160
+ http_version = token [2 ];
119
161
}
120
162
121
163
File actualFile =
@@ -160,8 +202,33 @@ public void run() {
160
202
out .write (message1 .body );
161
203
out .flush ();
162
204
}
163
- } else {
164
- // method is not "GET"
205
+
206
+ } else if (method .equals ("POST" )) {
207
+
208
+ //get the request body for POST method
209
+ //add 4, because the index that
210
+ //will be returned is relative to the
211
+ //very first occurence of the string
212
+ String requestBody =
213
+ userRequestToString
214
+ .substring (userRequestToString .lastIndexOf ("\r \n \r \n " ) + 4 );
215
+
216
+ //just showing the input data back to the client
217
+ //a lot of things can be done for the request body
218
+ //it can go directly to a file or a database,
219
+ //or be loaded into an XML file for further processing
220
+
221
+ //we use also the buffered out writer
222
+ //to make sure that the new line will be correct
223
+ //for all platforms
224
+ bufferedOut .write ("data recorded:" );
225
+ bufferedOut .newLine ();
226
+ bufferedOut .write (requestBody );
227
+ bufferedOut .flush ();
228
+
229
+ } else {
230
+
231
+ //not yet implemented methods
165
232
if (http_version .startsWith ("HTTP/" )) {
166
233
// send a MIME header
167
234
ServerHeader .serverHeader (out ,
@@ -186,4 +253,4 @@ public void run() {
186
253
}
187
254
}
188
255
189
- }
256
+ }
0 commit comments