Skip to content

Commit 8c6b12e

Browse files
committed
Using a lambda routing model for flexibility, and ease of use.
1 parent 9514d2b commit 8c6b12e

File tree

11 files changed

+276
-84
lines changed

11 files changed

+276
-84
lines changed

lib/src/main/java/com/devsegal/jserve/BaseHTTPServer.java

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@
44
import java.net.ServerSocket;
55
import java.net.Socket;
66
import java.util.HashMap;
7+
import java.nio.file.Path;
78

89
public class BaseHTTPServer implements Runnable {
910

1011
private int port = 80;
1112
private boolean isStopped = false;
12-
13-
private String serverPath = "";
14-
13+
14+
private NotFoundPageHandler notFoundPageHandler;
15+
private Path originalServerPath;
1516
private ServerSocket server;
1617
private HashMap<String, WebRouteHandler> routesToHandlers;
1718

@@ -20,10 +21,19 @@ public BaseHTTPServer(int port) {
2021
routesToHandlers = new HashMap<>();
2122
}
2223

23-
public void setupOrigin(String path) {
24-
serverPath = path;
24+
public void setupOriginalServerPath(Path path) {
25+
this.originalServerPath = path;
26+
}
27+
28+
public void setupOriginalServerPath(String path) {
29+
setupOriginalServerPath(Path.of(path));
2530
}
2631

32+
public void setupNotFoundPageHandler(NotFoundPageHandler notFoundPageHandler) {
33+
this.notFoundPageHandler = notFoundPageHandler;
34+
}
35+
36+
2737
public void route(String path, String method, WebRouteHandler handler) {
2838
routesToHandlers.put(path + method, handler);
2939
}
@@ -36,35 +46,17 @@ private void initializeServerSocket() {
3646
}
3747
}
3848

39-
/*
40-
public void parseRoutes() {
41-
File routesFile = new File(serverPath + "routes.txt");
42-
43-
try {
44-
BufferedReader reader = new BufferedReader(new FileReader(routesFile));
45-
String line;
46-
String[] paths;
47-
48-
while((line = reader.readLine()) != null) {
49-
paths = line.split(" ");
50-
routes.put(paths[0], paths[1]);
51-
}
52-
53-
System.out.println(routes.toString());
54-
55-
} catch (Exception e) {
56-
System.out.println(e.getMessage());
57-
}
58-
} */
59-
6049
private void acceptConectionsAndThrowToHandlers() {
6150
try {
6251
while (!isStopped) {
6352
Socket connection = server.accept();
6453

65-
(new Thread(new ConnectionHandler(connection, routesToHandlers, serverPath))).start();
54+
if(originalServerPath != null) {
55+
(new Thread(new ConnectionHandler( new ConnectionHandlerConfiguration(connection, routesToHandlers, originalServerPath, notFoundPageHandler) ))).start();
56+
} else {
57+
(new Thread(new ConnectionHandler( new ConnectionHandlerConfiguration(connection, routesToHandlers, notFoundPageHandler) ))).start();
58+
}
6659
}
67-
6860
} catch(IOException e) {
6961
System.out.println(e.getMessage());
7062
}

lib/src/main/java/com/devsegal/jserve/ConnectionHandler.java

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,38 @@
44
import java.io.IOException;
55
import java.io.BufferedReader;
66
import java.net.Socket;
7-
import java.nio.file.Files;
87
import java.util.HashMap;
98
import java.nio.file.Path;
10-
import java.util.function.Consumer;
119

1210
class ConnectionHandler implements Runnable {
1311

14-
StringBuilder requestContents;
1512
BufferedReader reader;
1613
ResponseWriter responseWriter;
1714
BufferedReader requestReader;
18-
Socket connection;
19-
HashMap<String, WebRouteHandler> routes;
20-
String serverPath;
15+
Path originalServerPath;
16+
Socket connection;
2117
String contentType;
22-
String responsePath;
18+
NotFoundPageHandler notFoundPageHandler;
19+
HashMap<String, WebRouteHandler> routesToHandlers;
2320

2421

25-
public ConnectionHandler(Socket connection, HashMap<String, WebRouteHandler> routes, String serverPath) {
26-
this.connection = connection;
27-
this.routes = routes;
28-
this.serverPath = serverPath;
29-
this.requestContents = new StringBuilder();
22+
public ConnectionHandler(ConnectionHandlerConfiguration configuration) {
23+
this.connection = configuration.getConnection();
24+
this.routesToHandlers = configuration.getRoutesToHandlers();
25+
this.notFoundPageHandler = configuration.getNotFoundPageHandler();
3026

27+
Path temporaryServerPath = configuration.getOriginalServerPath();
28+
if(temporaryServerPath != null) {
29+
this.originalServerPath = temporaryServerPath;
30+
}
31+
3132
try {
32-
responseWriter = new ResponseWriter(connection.getOutputStream());
33+
if(originalServerPath != null) {
34+
responseWriter = new ResponseWriter(connection.getOutputStream(), originalServerPath);
35+
} else {
36+
responseWriter = new ResponseWriter(connection.getOutputStream());
37+
}
38+
3339
} catch(IOException e) {
3440
e.printStackTrace();
3541
}
@@ -42,13 +48,14 @@ public ConnectionHandler(Socket connection, HashMap<String, WebRouteHandler> rou
4248
}
4349

4450
public void run() {
45-
RequestParser requestParser = new RequestParser();
46-
requestParser.parseRequest(requestReader);
51+
RequestParser requestParser = new RequestParser(requestReader);
52+
requestParser.parseRequest();
4753

48-
WebRouteHandler webRouteHandler = routes.get(requestParser.getPath() + requestParser.getMethod());
54+
WebRouteHandler webRouteHandler = routesToHandlers.get(requestParser.getPath() + requestParser.getMethod());
4955

56+
// If the page is not officially registered as a path, in other words - a 404 page is now necessary
5057
if(webRouteHandler == null) {
51-
responseWriter.send(); // response to invalid requests
58+
notFoundPageHandler.handle(requestParser, responseWriter);
5259
} else {
5360
webRouteHandler.handler(requestParser, responseWriter);
5461
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.devsegal.jserve;
2+
3+
import java.net.Socket;
4+
import java.util.HashMap;
5+
import java.nio.file.Path;
6+
7+
public class ConnectionHandlerConfiguration {
8+
private Socket connection;
9+
private HashMap<String, WebRouteHandler> routesToHandlers;
10+
private Path originalServerPath;
11+
private NotFoundPageHandler notFoundPageHandler;
12+
13+
public ConnectionHandlerConfiguration(Socket connection, HashMap<String, WebRouteHandler> routesToHandlers) {
14+
this.connection = connection;
15+
this.routesToHandlers = routesToHandlers;
16+
}
17+
18+
public ConnectionHandlerConfiguration(Socket connection, HashMap<String, WebRouteHandler> routesToHandlers, NotFoundPageHandler notFoundPageHandler) {
19+
this(connection, routesToHandlers);
20+
this.notFoundPageHandler = notFoundPageHandler;
21+
}
22+
23+
public ConnectionHandlerConfiguration(Socket connection, HashMap<String, WebRouteHandler> routesToHandlers, Path originalServerPath) {
24+
this.connection = connection;
25+
this.routesToHandlers = routesToHandlers;
26+
this.originalServerPath = originalServerPath;
27+
}
28+
29+
public ConnectionHandlerConfiguration(Socket connection, HashMap<String, WebRouteHandler> routesToHandlers, Path originalServerPath, NotFoundPageHandler notFoundPageHandler) {
30+
this(connection, routesToHandlers, originalServerPath);
31+
this.notFoundPageHandler = notFoundPageHandler;
32+
}
33+
34+
public Socket getConnection() {
35+
return connection;
36+
}
37+
38+
public HashMap<String, WebRouteHandler> getRoutesToHandlers() {
39+
return routesToHandlers;
40+
}
41+
42+
public Path getOriginalServerPath() {
43+
return originalServerPath;
44+
}
45+
46+
public NotFoundPageHandler getNotFoundPageHandler() {
47+
return notFoundPageHandler;
48+
}
49+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.devsegal.jserve;
2+
3+
import java.io.BufferedReader;
4+
5+
public interface FilterData<T> {
6+
public boolean badData(T data, BufferedReader reader);
7+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.devsegal.jserve;
2+
3+
public interface NotFoundPageHandler {
4+
public void handle(RequestParser request, ResponseWriter response);
5+
}

lib/src/main/java/com/devsegal/jserve/Request.java

Lines changed: 0 additions & 11 deletions
This file was deleted.

lib/src/main/java/com/devsegal/jserve/RequestParser.java

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,31 +8,73 @@ public class RequestParser {
88
private String method = "";
99
private String path = "";
1010
private String httpVersion = "";
11+
private BufferedReader reader;
1112
private HashMap<String, String> headers;
12-
1313

14-
public RequestParser() {
14+
15+
public RequestParser(BufferedReader reader) {
16+
this.reader = reader;
1517
headers = new HashMap<>();
1618
}
1719

18-
public void parseRequest(BufferedReader reader) {
20+
public void getHeaders(FilterData<String> filterData) {
1921
try {
20-
if(reader.ready()) {
21-
String[] firstLine = reader.readLine().split(" "); // should be the METHOD PATH HTTP VERSION
22-
23-
method = firstLine[0];
24-
path = firstLine[1];
25-
httpVersion = firstLine[2];
26-
}
27-
2822
while(reader.ready()) {
2923
String line = reader.readLine();
24+
25+
// if the filter has found a reason to stop continuing
26+
if(filterData.badData(line, reader)) {
27+
break;
28+
}
29+
3030
String[] header = line.split(":", 2);
3131

32+
System.out.println(line);
33+
3234
if(header.length == 2) {
3335
headers.put(header[0], header[1]);
3436
}
3537
}
38+
} catch(IOException e) {
39+
e.printStackTrace();
40+
}
41+
}
42+
43+
public void parseRequest() {
44+
try {
45+
boolean waitingForInformation = true;
46+
47+
while(waitingForInformation) {
48+
if(reader.ready()) {
49+
waitingForInformation = false;
50+
51+
String[] firstLine = reader.readLine().split(" "); // should be the METHOD PATH HTTP VERSION
52+
53+
method = firstLine[0];
54+
path = firstLine[1];
55+
httpVersion = firstLine[2];
56+
}
57+
}
58+
59+
if(method.equals("GET")) {
60+
getHeaders((data, reader) -> {
61+
return true;
62+
});
63+
} else if(method.equals("POST")) {
64+
getHeaders((data, reader) -> {
65+
if(data.length() == 0) {
66+
try {
67+
while(reader.ready())
68+
System.out.println("post data: " + reader.readLine());
69+
} catch(IOException e) {
70+
e.printStackTrace();
71+
}
72+
return true;
73+
} else {
74+
return false;
75+
}
76+
});
77+
}
3678
} catch (IOException e) {
3779
e.printStackTrace();
3880
}

lib/src/main/java/com/devsegal/jserve/Response.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@
22

33
interface Response {
44

5-
StringBuilder respContents = new StringBuilder();
6-
boolean bodyContentInserted = false;
5+
StringBuilder responseContents = new StringBuilder();
76

8-
public void setContentType(String contentType);
9-
public void setConnectionType(String connectionType);
7+
public void setResponseHeaders(ResponseHeaders responseHeaders);
108
public void insertContent(String content);
119
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.devsegal.jserve;
2+
3+
import java.util.EnumSet;
4+
5+
public class ResponseHeaders {
6+
private STATUS responseStatus;
7+
private int responseCode;
8+
9+
private String contentType;
10+
private String connectionType;
11+
12+
public ResponseHeaders(STATUS responseStatus, int responseCode, String contentType, String connectionType) {
13+
this.responseStatus = responseStatus;
14+
this.responseCode = responseCode;
15+
this.contentType = contentType;
16+
this.connectionType = connectionType;
17+
}
18+
19+
public ResponseHeaders(String contentType, String connectionType) {
20+
this(STATUS.OK, 200, contentType, connectionType);
21+
}
22+
23+
public static String convertResponseStatusToString(ResponseHeaders responseHeaders) {
24+
return responseHeaders.getResponseStatus().name().replace("_", " ");
25+
}
26+
27+
public STATUS getResponseStatus() {
28+
return responseStatus;
29+
}
30+
31+
public int getResponseCode() {
32+
return responseCode;
33+
}
34+
35+
public String getContentType() {
36+
return contentType;
37+
}
38+
39+
public String getConnectionType() {
40+
return connectionType;
41+
}
42+
43+
public static String convertToString(ResponseHeaders responseHeaders) {
44+
StringBuilder responseString = new StringBuilder();
45+
46+
String firstLineResponsePrefix = "HTTP 1.1/";
47+
responseString.append(firstLineResponsePrefix + responseHeaders.getResponseCode() + " ");
48+
responseString.append(ResponseHeaders.convertResponseStatusToString(responseHeaders) + "\n");
49+
50+
responseString.append("Connection-type:" + responseHeaders.getConnectionType() + "\n");
51+
52+
responseString.append("Content-type:" + responseHeaders.getContentType() + "\n");
53+
54+
// before adding the content, add one line in between headers and body
55+
responseString.append("\n");
56+
57+
return responseString.toString();
58+
}
59+
}

0 commit comments

Comments
 (0)