Skip to content
This repository was archived by the owner on Jul 31, 2022. It is now read-only.

Commit a2176a1

Browse files
authored
Added Throttled Handler
Added Throttled Handler
2 parents 124d9fd + a623475 commit a2176a1

9 files changed

+414
-5
lines changed

src/main/java/com/kttdevelopment/simplehttpserver/HttpSessionHandler.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ public synchronized String assignSessionID(final HttpExchange exchange){
5959
* Returns the session of the client or assigns one if it does not yet have one Session will only be saved client side if the exchange headers are sent using {@link HttpExchange#sendResponseHeaders(int, long)}.
6060
*
6161
* @param exchange http exchange
62+
* @return session associated with the exchange
6263
*
6364
* @since 03.03.00
6465
* @author Ktt Development
@@ -136,6 +137,7 @@ public final String toString(){
136137
.setHttpOnly(true)
137138
.build();
138139
exchange.getResponseHeaders().add("Set-Cookie",out.toCookieHeaderString());
140+
sessions.put(sessionId,session);
139141
}else{
140142
session = sessions.get(sessionId);
141143
}

src/main/java/com/kttdevelopment/simplehttpserver/SimpleHttpCookie.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,17 +113,17 @@ public final String toCookieHeaderString(){
113113
final StringBuilder OUT = new StringBuilder();
114114
OUT.append(name).append("=").append(value);
115115
if(expires != null)
116-
OUT.append("; Expires=").append(new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss").format(expires)).append(" GMT");
116+
OUT.append("; Expires=").append(sdf.format(expires)).append(" GMT");
117117
if(maxAge != null)
118118
OUT.append("; Max-Age=").append(maxAge);
119119
if(domain != null)
120120
OUT.append("; Domain=").append(domain);
121121
if(path != null)
122122
OUT.append("; Path=").append(path);
123123
if(secure != null && secure)
124-
OUT.append("; Secure=").append(secure);
124+
OUT.append("; Secure=").append(true);
125125
if(httpOnly != null && httpOnly)
126-
OUT.append("; HttpOnly=").append(httpOnly);
126+
OUT.append("; HttpOnly=").append(true);
127127
if(sameSite != null)
128128
OUT.append("; SameSite=").append(sameSite);
129129

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.kttdevelopment.simplehttpserver.handler;
2+
3+
import com.sun.net.httpserver.HttpExchange;
4+
5+
/**
6+
* Determines how connections are handled by the {@link ThrottledHandler}.
7+
*
8+
* @see ServerThrottler
9+
* @see SessionThrottler
10+
* @since 03.03.00
11+
* @version 03.03.00
12+
* @author Ktt Development
13+
*/
14+
abstract class ConnectionThrottler {
15+
16+
/**
17+
* Adds a connection to the pool.
18+
*
19+
* @param exchange exchange to process
20+
* @return if exchange was able to be added
21+
*
22+
* @see #deleteConnection(HttpExchange)
23+
* @since 03.03.00
24+
* @author Ktt Development
25+
*/
26+
abstract boolean addConnection(final HttpExchange exchange);
27+
28+
/**
29+
* Removes a connection from the pool.
30+
*
31+
* @param exchange exchange to process
32+
*
33+
* @see #addConnection(HttpExchange)
34+
* @since 03.03.00
35+
* @author Ktt Development
36+
*/
37+
abstract void deleteConnection(final HttpExchange exchange);
38+
39+
}

src/main/java/com/kttdevelopment/simplehttpserver/handler/DirectoryEntry.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
* @version 02.00.00
1616
* @author Ktt Development
1717
*/
18-
@SuppressWarnings("SpellCheckingInspection")
1918
class DirectoryEntry {
2019

2120
private final boolean isWalkthrough;

src/main/java/com/kttdevelopment/simplehttpserver/handler/RedirectHandler.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ public final void handle(final SimpleHttpExchange exchange) throws IOException{
4040

4141
//
4242

43-
4443
@SuppressWarnings("StringBufferReplaceableByString")
4544
@Override
4645
public String toString(){

src/main/java/com/kttdevelopment/simplehttpserver/handler/SSEHandler.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@
1212
import java.util.concurrent.TimeUnit;
1313
import java.util.concurrent.atomic.AtomicInteger;
1414

15+
/**
16+
* A SSE handler allows server to client events by using an <code>text/event-stream</code>. Events are sent using {@link #push(String)} or {@link #push(String, int, String)}.
17+
*
18+
* @see SimpleHttpHandler
19+
* @since 03.01.00
20+
* @version 03.03.00
21+
* @author Ktt Development
22+
*/
1523
public class SSEHandler implements SimpleHttpHandler {
1624

1725
private final List<OutputStream> listeners = new ArrayList<>();
@@ -48,10 +56,30 @@ public final void handle(final SimpleHttpExchange exchange) throws IOException{
4856
listeners.add(exchange.getOutputStream());
4957
}
5058

59+
/**
60+
* Pushes an event to the stream.
61+
*
62+
* @param data data to send
63+
*
64+
* @see #push(String, int, String)
65+
* @since 03.01.00
66+
* @author Ktt Development
67+
*/
5168
public synchronized final void push(final String data){
5269
push(data,0,"");
5370
}
5471

72+
/**
73+
* Pushes an event to the stream.
74+
*
75+
* @param data data to send
76+
* @param retry how long to retry for
77+
* @param event event type
78+
*
79+
* @see #push(String)
80+
* @since 03.01.00
81+
* @author Ktt Development
82+
*/
5583
public synchronized final void push(final String data, final int retry, final String event){
5684
eventId.addAndGet(1);
5785
final EventStreamRecord record = new EventStreamRecord(retry,event,data);
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
package com.kttdevelopment.simplehttpserver.handler;
2+
3+
import com.sun.net.httpserver.HttpExchange;
4+
5+
import java.util.concurrent.atomic.AtomicInteger;
6+
import java.util.function.Predicate;
7+
8+
/**
9+
* Limits connections for the server.
10+
*
11+
* @see ThrottledHandler
12+
* @see SessionThrottler
13+
* @since 03.03.00
14+
* @version 03.03.00
15+
* @author Ktt Development
16+
*/
17+
public class ServerThrottler extends ConnectionThrottler {
18+
19+
private final Predicate<HttpExchange> countsTowardsLimit;
20+
private final AtomicInteger connections = new AtomicInteger(0);
21+
22+
private final AtomicInteger maxConnections = new AtomicInteger(0);
23+
24+
/**
25+
* Creates a throttler that allows no connections.
26+
*
27+
* @since 03.03.00
28+
* @author Ktt Development
29+
*/
30+
public ServerThrottler(){
31+
countsTowardsLimit = exchange -> true;
32+
}
33+
34+
/**
35+
* Creates a throttler that allows a certain amount of simultaneous connections.
36+
*
37+
* @param maxConnections maximum simultaneous connections
38+
*
39+
* @since 03.03.00
40+
* @author Ktt Development
41+
*/
42+
public ServerThrottler(final int maxConnections){
43+
countsTowardsLimit = exchange -> true;
44+
this.maxConnections.set(maxConnections);
45+
}
46+
47+
/**
48+
* Creates a throttler that allows a certain amount of simultaneous connections and exempt connections.
49+
*
50+
* @param countsTowardsLimit determines which exchanges count towards the connection limit
51+
*
52+
* @since 03.03.00
53+
* @author Ktt Development
54+
*/
55+
public ServerThrottler(final Predicate<HttpExchange> countsTowardsLimit){
56+
this.countsTowardsLimit = countsTowardsLimit;
57+
}
58+
59+
/**
60+
* Creates a throttler that allows a certain amount of simultaneous connections and exempt connections.
61+
*
62+
* @param countsTowardsLimit determines which exchanges count towards the connection limit
63+
* @param maxConnections maximum simultaneous connections
64+
*
65+
* @since 03.03.00
66+
* @author Ktt Development
67+
*/
68+
public ServerThrottler(final Predicate<HttpExchange> countsTowardsLimit, final int maxConnections){
69+
this.countsTowardsLimit = countsTowardsLimit;
70+
this.maxConnections.set(maxConnections);
71+
}
72+
73+
/**
74+
* Returns the maximum allowed connections.
75+
*
76+
* @return maximum allowed connections
77+
*
78+
* @see #setMaxConnections(int)
79+
* @since 03.03.00
80+
* @author Ktt Development
81+
*/
82+
public final int getMaxConnections(){
83+
return maxConnections.get();
84+
}
85+
86+
/**
87+
* Sets the maximum allowed connections. Must be a positive number.
88+
*
89+
* @param maxConnections maximum allowed connections
90+
*
91+
* @see #getMaxConnections()
92+
* @since 03.03.00
93+
* @author Ktt Development
94+
*/
95+
public synchronized final void setMaxConnections(final int maxConnections){
96+
if(maxConnections >= 0)
97+
this.maxConnections.set(maxConnections);
98+
}
99+
100+
final boolean addConnection(final HttpExchange exchange){
101+
if(!countsTowardsLimit.test(exchange)){
102+
return true;
103+
}else{
104+
synchronized(this){
105+
if(connections.get() + 1 <= maxConnections.get()){
106+
connections.incrementAndGet();
107+
return true;
108+
}
109+
}
110+
}
111+
return false;
112+
}
113+
114+
final void deleteConnection(final HttpExchange exchange){
115+
if(countsTowardsLimit.test(exchange))
116+
synchronized(this){
117+
connections.decrementAndGet();
118+
}
119+
}
120+
121+
//
122+
123+
@SuppressWarnings("StringBufferReplaceableByString")
124+
@Override
125+
public String toString(){
126+
final StringBuilder OUT = new StringBuilder();
127+
128+
OUT.append("ConnectionThrottler") .append('{');
129+
OUT.append("condition") .append('=') .append(countsTowardsLimit) .append(", ");
130+
OUT.append("connections") .append('=') .append(connections.get()) .append(", ");
131+
OUT.append("maxConnections") .append('=') .append(maxConnections.get());
132+
OUT.append('}');
133+
134+
return OUT.toString();
135+
}
136+
137+
}

0 commit comments

Comments
 (0)