Skip to content

Commit 75b150a

Browse files
committed
Refactor middleware-system
1 parent e1c65df commit 75b150a

15 files changed

+198
-252
lines changed

src/express/Express.java

Lines changed: 37 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,16 @@
33
import com.sun.net.httpserver.HttpServer;
44
import express.events.Action;
55
import express.events.HttpRequest;
6-
import express.expressfilter.ExpressFilter;
76
import express.expressfilter.ExpressFilterChain;
7+
import express.expressfilter.ExpressFilterImpl;
8+
import express.expressfilter.ExpressFilterTask;
9+
import express.expressfilter.ExpressFilterWorker;
810
import express.http.Request;
911
import express.http.Response;
10-
import express.middleware.ExpressWorker;
1112

1213
import java.io.IOException;
1314
import java.net.InetSocketAddress;
1415
import java.util.ArrayList;
15-
import java.util.Collections;
16-
import java.util.List;
1716

1817
/**
1918
* @author Simon Reinisch
@@ -23,49 +22,52 @@
2322
*/
2423
public class Express {
2524

26-
private final List<ExpressWorker> WORKERS = Collections.synchronizedList(new ArrayList<>());
25+
private final ArrayList<ExpressFilterWorker> WORKER = new ArrayList<>();
26+
private final ExpressFilterChain MIDDLEWARE_CHAIN = new ExpressFilterChain();
2727
private final ExpressFilterChain FILTER_CHAIN = new ExpressFilterChain();
2828

2929
private HttpServer httpServer;
3030

3131
/**
3232
* Add an middleware which will be firea BEFORE EACH request-type listener will be fired.
3333
*
34-
* @param request An listener which will be fired on every equestmethod- and path.
34+
* @param middleware An middleware which will be fired on every equestmethod- and path.
3535
*/
36-
public void use(HttpRequest request) {
37-
addFilter(true, "*", "*", request);
36+
public void use(HttpRequest middleware) {
37+
addMiddleware("*", "*", middleware);
3838
}
3939

4040
/**
4141
* Add an middleware which will be firea BEFORE EACH request-type listener will be fired.
4242
*
43-
* @param context The context where the middleware should listen, see README for information about placeholder.
44-
* @param request An listener which will be fired if the context matches the requestpath.
43+
* @param context The context where the middleware should listen, see README for information about placeholder.
44+
* @param middleware An middleware which will be fired if the context matches the requestpath.
4545
*/
46-
public void use(String context, HttpRequest request) {
47-
addFilter(true, "*", context, request);
46+
public void use(String context, HttpRequest middleware) {
47+
addMiddleware("*", context, middleware);
4848
}
4949

5050
/**
5151
* Add an middleware which will be firea BEFORE EACH request-type listener will be fired.
5252
*
5353
* @param context The context where the middleware should listen, see README for information about placeholder.
5454
* @param requestMethod And type of request-method eg. GET, POST etc.
55-
* @param request An listener which will be fired if the context matches the requestmethod- and path.
55+
* @param middleware An middleware which will be fired if the context matches the requestmethod- and path.
5656
*/
57-
public void use(String context, String requestMethod, HttpRequest request) {
58-
addFilter(true, requestMethod.toUpperCase(), context, request);
57+
public void use(String context, String requestMethod, HttpRequest middleware) {
58+
addMiddleware(requestMethod.toUpperCase(), context, middleware);
59+
}
60+
61+
private void addMiddleware(String requestMethod, String context, HttpRequest middleware) {
62+
if (middleware instanceof ExpressFilterTask) {
63+
WORKER.add(new ExpressFilterWorker((ExpressFilterTask) middleware));
64+
}
65+
66+
MIDDLEWARE_CHAIN.add(new ExpressFilterImpl(requestMethod, context, middleware));
5967
}
6068

61-
/**
62-
* Add an listener for request types.
63-
*
64-
* @param context The context, see README for information about placeholder.
65-
* @param request An listener.
66-
*/
6769
public void all(String context, HttpRequest request) {
68-
addFilter(false, "*", context, request);
70+
FILTER_CHAIN.add(new ExpressFilterImpl("*", context, request));
6971
}
7072

7173
/**
@@ -75,7 +77,7 @@ public void all(String context, HttpRequest request) {
7577
* @param request An listener which will be fired if the context matches the requestpath.
7678
*/
7779
public void get(String context, HttpRequest request) {
78-
addFilter(false, "GET", context, request);
80+
FILTER_CHAIN.add(new ExpressFilterImpl("GET", context, request));
7981
}
8082

8183
/**
@@ -85,7 +87,7 @@ public void get(String context, HttpRequest request) {
8587
* @param request An listener which will be fired if the context matches the requestpath.
8688
*/
8789
public void post(String context, HttpRequest request) {
88-
addFilter(false, "POST", context, request);
90+
FILTER_CHAIN.add(new ExpressFilterImpl("POST", context, request));
8991
}
9092

9193
/**
@@ -95,7 +97,7 @@ public void post(String context, HttpRequest request) {
9597
* @param request An listener which will be fired if the context matches the requestpath.
9698
*/
9799
public void put(String context, HttpRequest request) {
98-
addFilter(false, "PUT", context, request);
100+
FILTER_CHAIN.add(new ExpressFilterImpl("PUT", context, request));
99101
}
100102

101103
/**
@@ -105,7 +107,7 @@ public void put(String context, HttpRequest request) {
105107
* @param request An listener which will be fired if the context matches the requestpath.
106108
*/
107109
public void delete(String context, HttpRequest request) {
108-
addFilter(false, "DELETE", context, request);
110+
FILTER_CHAIN.add(new ExpressFilterImpl("DELETE", context, request));
109111
}
110112

111113
/**
@@ -115,31 +117,7 @@ public void delete(String context, HttpRequest request) {
115117
* @param request An listener which will be fired if the context matches the requestpath.
116118
*/
117119
public void patch(String context, HttpRequest request) {
118-
addFilter(false, "PATCH", context, request);
119-
}
120-
121-
/**
122-
* Internal method to add an filter
123-
*
124-
* @param middleware If the filter is an middleware
125-
* @param requestMethod The request-method
126-
* @param context The url-path
127-
* @param request An listener which will be fired if the given context is matching
128-
*/
129-
private void addFilter(boolean middleware, String requestMethod, String context, HttpRequest request) {
130-
ExpressFilter handler = new ExpressFilter(requestMethod, context, request);
131-
132-
if (request instanceof ExpressWorker){
133-
((ExpressWorker) request).start();
134-
WORKERS.add((ExpressWorker) request);
135-
}
136-
137-
138-
// Middleware needs an seperated list because it will ALWAYS fired before each request handler
139-
if (middleware)
140-
FILTER_CHAIN.addMiddleware(handler);
141-
else
142-
FILTER_CHAIN.addFilter(handler);
120+
FILTER_CHAIN.add(new ExpressFilterImpl("PATCH", context, request));
143121
}
144122

145123
/**
@@ -186,12 +164,20 @@ public void listen(Action onStart) throws IOException {
186164
public void listen(Action onStart, int port) throws IOException {
187165
new Thread(() -> {
188166
try {
167+
// Fire worker threads
168+
WORKER.forEach(ExpressFilterWorker::start);
169+
170+
171+
// Create http server
189172
httpServer = HttpServer.create(new InetSocketAddress("localhost", port), 0);
190173
httpServer.setExecutor(null);
191174

192175
httpServer.createContext("/", httpExchange -> {
193176
Request request = new Request(httpExchange);
194177
Response response = new Response(httpExchange);
178+
179+
// First fire all middlewares, then the normal request filter
180+
MIDDLEWARE_CHAIN.filter(request, response);
195181
FILTER_CHAIN.filter(request, response);
196182
});
197183

src/express/expressfilter/AbstractExpressFilter.java

Lines changed: 0 additions & 12 deletions
This file was deleted.
Lines changed: 8 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,11 @@
11
package express.expressfilter;
22

3-
import express.events.HttpRequest;
4-
import express.http.Request;
5-
import express.http.Response;
6-
7-
import java.util.HashMap;
8-
import java.util.regex.Matcher;
9-
import java.util.regex.Pattern;
10-
11-
/**
12-
* @author Simon Reinisch
13-
* @implNote Core modul of express, don't change anything.
14-
* <p>
15-
* Filter to handle request handling & parsing.
16-
*/
17-
public class ExpressFilter extends AbstractExpressFilter {
18-
19-
private final HttpRequest REQUEST;
20-
private final String REQUEST_METHOD;
21-
22-
private final String CONTEXT;
23-
private final String[] CONTEXT_PARAMS;
24-
private final String CONTEXT_REGEX;
25-
private final Pattern CONTEXT_PATTERN;
26-
27-
public ExpressFilter(String requestMethod, String context, HttpRequest httpRequest) {
28-
this.REQUEST_METHOD = requestMethod;
29-
this.REQUEST = httpRequest;
30-
31-
this.CONTEXT = context;
32-
this.CONTEXT_PARAMS = context.split("(/)(:|[^:]+|)(:|)");
33-
this.CONTEXT_REGEX = "\\Q" + context.replaceAll(":([^/]+)", "\\\\E([^/]+)\\\\Q") + "\\E";
34-
this.CONTEXT_PATTERN = Pattern.compile(CONTEXT_REGEX);
35-
}
36-
37-
@Override
38-
public void doFilter(Request req, Response res, ExpressFilterChain chain) {
39-
String requestMethod = req.getMethod();
40-
String requestPath = req.getURI().getRawPath();
41-
42-
if (!requestMethod.equals(REQUEST_METHOD) || (REQUEST_METHOD.equals("*") && CONTEXT.equals("*"))) {
43-
REQUEST.handle(req, res);
44-
return;
45-
}
46-
47-
if (!requestPath.matches(CONTEXT_REGEX) && !CONTEXT.equals("*")) {
48-
return;
49-
}
50-
51-
// Parse params, see README
52-
HashMap<String, String> params = new HashMap<>();
53-
Matcher matcher = CONTEXT_PATTERN.matcher(requestPath);
54-
55-
// Match all params
56-
if (matcher.find()) {
57-
58-
for (int i = 1; i <= matcher.groupCount() && i < CONTEXT_PARAMS.length; i++) {
59-
String g = matcher.group(i);
60-
params.put(CONTEXT_PARAMS[i], g);
61-
}
62-
63-
} else {
64-
return;
65-
}
66-
67-
req.setParams(params);
68-
REQUEST.handle(req, res);
69-
}
3+
public interface ExpressFilter {
4+
5+
/**
6+
* Identifier for the middleware
7+
*
8+
* @return
9+
*/
10+
String getName();
7011
}

src/express/expressfilter/ExpressFilterChain.java

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package express.expressfilter;
22

3+
import express.events.HttpRequest;
34
import express.http.Request;
45
import express.http.Response;
56

@@ -8,25 +9,20 @@
89
import java.util.List;
910
import java.util.ListIterator;
1011

11-
public class ExpressFilterChain {
12+
public class ExpressFilterChain <T extends HttpRequest> {
1213

13-
private List<ExpressFilter> expressFilterList = Collections.synchronizedList(new ArrayList<ExpressFilter>());
14+
private List<T> expressFilters = Collections.synchronizedList(new ArrayList<>());
1415

15-
public void addFilter(ExpressFilter expressFilter) {
16-
expressFilterList.add(expressFilter);
17-
}
18-
19-
public void addMiddleware(ExpressFilter expressFilter) {
20-
expressFilterList.add(0, expressFilter);
16+
public void add(T expressFilter) {
17+
expressFilters.add(expressFilter);
2118
}
2219

2320
public void filter(Request req, Response res) {
24-
ListIterator<ExpressFilter> iter = expressFilterList.listIterator();
21+
ListIterator<T> iter = expressFilters.listIterator();
2522

2623
while (!res.isClosed() && iter.hasNext()) {
2724
if (iter.hasNext()) {
28-
AbstractExpressFilter expressFilter = iter.next();
29-
expressFilter.doFilter(req, res, this);
25+
iter.next().handle(req, res);
3026
}
3127
}
3228
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package express.expressfilter;
2+
3+
import express.events.HttpRequest;
4+
import express.http.Request;
5+
import express.http.Response;
6+
7+
import java.util.HashMap;
8+
import java.util.regex.Matcher;
9+
import java.util.regex.Pattern;
10+
11+
/**
12+
* @author Simon Reinisch
13+
* @implNote Core modul of express, don't change anything.
14+
* <p>
15+
* Filter to handle request handling & parsing.
16+
*/
17+
public class ExpressFilterImpl implements HttpRequest {
18+
19+
private final HttpRequest REQUEST;
20+
private final String REQUEST_METHOD;
21+
22+
private final String CONTEXT;
23+
private final String[] CONTEXT_PARAMS;
24+
private final String CONTEXT_REGEX;
25+
private final Pattern CONTEXT_PATTERN;
26+
27+
public ExpressFilterImpl(String requestMethod, String context, HttpRequest httpRequest) {
28+
this.REQUEST_METHOD = requestMethod;
29+
this.REQUEST = httpRequest;
30+
31+
this.CONTEXT = context;
32+
this.CONTEXT_PARAMS = context.split("(/)(:|[^:]+|)(:|)");
33+
this.CONTEXT_REGEX = "\\Q" + context.replaceAll(":([^/]+)", "\\\\E([^/]+)\\\\Q") + "\\E";
34+
this.CONTEXT_PATTERN = Pattern.compile(CONTEXT_REGEX);
35+
}
36+
37+
@Override
38+
public void handle(Request req, Response res) {
39+
String requestMethod = req.getMethod();
40+
String requestPath = req.getURI().getRawPath();
41+
42+
if (!requestMethod.equals(REQUEST_METHOD) || (REQUEST_METHOD.equals("*") && CONTEXT.equals("*"))) {
43+
REQUEST.handle(req, res);
44+
return;
45+
}
46+
47+
if (!requestPath.matches(CONTEXT_REGEX) && !CONTEXT.equals("*")) {
48+
return;
49+
}
50+
51+
// Parse params, see README
52+
HashMap<String, String> params = new HashMap<>();
53+
Matcher matcher = CONTEXT_PATTERN.matcher(requestPath);
54+
55+
// Match all params
56+
if (matcher.find()) {
57+
58+
for (int i = 1; i <= matcher.groupCount() && i < CONTEXT_PARAMS.length; i++) {
59+
String g = matcher.group(i);
60+
params.put(CONTEXT_PARAMS[i], g);
61+
}
62+
63+
} else {
64+
return;
65+
}
66+
67+
req.setParams(params);
68+
REQUEST.handle(req, res);
69+
}
70+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package express.expressfilter;
2+
3+
4+
public interface ExpressFilterTask {
5+
6+
long getDelay();
7+
8+
void onUpdate();
9+
10+
void onStart();
11+
12+
void onStop();
13+
}

0 commit comments

Comments
 (0)