Skip to content

Commit 6239765

Browse files
Add files via upload
1 parent c62bbd9 commit 6239765

File tree

6 files changed

+335
-0
lines changed

6 files changed

+335
-0
lines changed
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
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+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package xdvrx1_serverProject;
2+
3+
class FileNotFoundMessage {
4+
5+
String body =
6+
new StringBuilder("<html>\r\n")
7+
.append("<head><title>File Not Found</title>\r\n")
8+
.append("</head>\r\n")
9+
.append("<body>")
10+
.append("<h1>HTTP Error 404: File Not Found [Try again later]</h1>\r\n")
11+
.append("</body></html>\r\n")
12+
.toString();
13+
14+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package xdvrx1_serverProject;
2+
3+
/*
4+
* This is the actual server class.
5+
* This will call the overridden
6+
* method `run()` of `Runnable`.
7+
*/
8+
9+
import java.util.concurrent.*;
10+
import java.util.logging.*;
11+
12+
import java.io.*;
13+
import java.net.*;
14+
15+
public class FileWebServer {
16+
17+
private final File rootDirectory;
18+
private final int port;
19+
private static final int pool_count = 10000;
20+
private static final String defaultPage = "index.html";
21+
22+
private static final Logger
23+
serverLogger = Logger.getLogger(FileWebServer
24+
.class.getCanonicalName());
25+
26+
//the constructor
27+
public FileWebServer(File rootDirectory, int port)
28+
throws IOException {
29+
30+
if (!rootDirectory.isDirectory()) {
31+
throw new IOException(rootDirectory
32+
+ " is not a directory");
33+
}
34+
35+
this.rootDirectory = rootDirectory;
36+
this.port = port;
37+
38+
}
39+
40+
//void start
41+
public void start()
42+
throws IOException {
43+
44+
ExecutorService pool =
45+
Executors.newFixedThreadPool(pool_count);
46+
47+
try (ServerSocket server = new ServerSocket(port)) {
48+
49+
serverLogger.info("Listening on port " + server.getLocalPort());
50+
serverLogger.info("@DocumentRoot");
51+
52+
while (true) {
53+
try {
54+
Socket request = server.accept();
55+
Runnable r =
56+
new ClientRequest(rootDirectory, defaultPage, request);
57+
pool.submit(r);
58+
} catch (IOException ex) {
59+
serverLogger.log(Level.WARNING, "Error accepting connection", ex);
60+
}
61+
}
62+
}
63+
}
64+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package xdvrx1_serverProject;
2+
3+
import java.io.*;
4+
5+
class MainMethod {
6+
public static void main(String[] args) {
7+
8+
try {
9+
10+
//the relative root directory
11+
//it's up to you if you want to change this
12+
File currentDir = new File(".");
13+
14+
//create an instance of `FileWebServer`
15+
//at the current directory and using port 80
16+
//again, it is up to you when you want to change
17+
//the port
18+
FileWebServer filewebserver = new FileWebServer(currentDir, 80);
19+
20+
//call `start` method that
21+
//contains the call for the Runnable `run`
22+
//of `ClientRequest` class
23+
filewebserver.start();
24+
25+
} catch (IOException ex) {
26+
//throws an exception if `currentDir`
27+
//is not recognized as such
28+
System.out.println(ex);
29+
}
30+
}
31+
32+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package xdvrx1_serverProject;
2+
3+
class NotSupportedMessage {
4+
5+
String body = new StringBuilder("<html>\r\n")
6+
.append("<head><title>Not Implemented</title>\r\n")
7+
.append("</head>\r\n")
8+
.append("<body>")
9+
.append("<h1>HTTP Error 501: Not Yet Supported Method</h1>\r\n")
10+
.append("</body></html>\r\n")
11+
.toString();
12+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package xdvrx1_serverProject;
2+
3+
import java.util.*;
4+
import java.io.*;
5+
6+
class ServerHeader {
7+
8+
private static Date current = new Date();
9+
10+
static void serverHeader(Writer out,
11+
String responseCode,
12+
String contentType,
13+
int length)
14+
throws IOException {
15+
16+
out.write(responseCode + "\r\n");
17+
out.write("Date: " + current + "\r\n");
18+
out.write("Server: `xdvrx1_Server` 2.0\r\n");
19+
out.write("Content-length: " + length + "\r\n");
20+
out.write("Content-type: " + contentType + "\r\n\r\n");
21+
out.flush();
22+
}
23+
24+
}

0 commit comments

Comments
 (0)