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

Commit be0d67d

Browse files
authored
V03.01+sse (#19)
* Started SSE * SSE Success! * Added closed and removed debug * Update pom.xml Co-authored-by: Katsute <[email protected]>
1 parent 8be618e commit be0d67d

File tree

8 files changed

+124
-14
lines changed

8 files changed

+124
-14
lines changed

.gitignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ out
55
# Project ignore
66
.docs
77
src/LICENSE.txt
8-
src/_ignore
8+
/src/main/java/com/kttdevelopment/simplehttpserver/_ignore/
99
# Gradle
1010
.gradle
1111
# Maven
12-
target
12+
target

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ Get requests are parsed into a hashmap.
2222
Post requests are parsed into a hashmap (`multipart/form-data` as well!).
2323

2424
## Http Handlers
25+
### SSE Handler
26+
Sever sent event events made easy.
2527
### Redirect Handler
2628
A simple handler to redirect links without leaving a mark in the history.
2729
### Predicate Handler

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>com.kttdevelopment</groupId>
88
<artifactId>simplehttpserver</artifactId>
9-
<version>03.00.01</version>
9+
<version>03.01.00</version>
1010
<packaging>jar</packaging>
1111

1212
<dependencies>

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.kttdevelopment.simplehttpserver.var.RequestMethod;
66

77
import java.io.IOException;
8+
import java.io.OutputStream;
89
import java.net.InetSocketAddress;
910
import java.net.URI;
1011
import java.util.HashMap;
@@ -335,6 +336,15 @@ static SimpleHttpExchange create(final HttpExchange exchange){
335336

336337
//
337338

339+
/**
340+
* Returns the exchange response stream.
341+
* @return exchange output stream
342+
*
343+
* @since 03.01.00
344+
* @author Ktt Development
345+
*/
346+
public abstract OutputStream getOutputStream();
347+
338348
/**
339349
* Sends response headers to the client.
340350
*

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

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ static SimpleHttpExchange createSimpleHttpExchange(final HttpExchange exchange){
6262

6363
private final HashMap<String,String> cookies;
6464

65+
private final OutputStream outputStream;
66+
6567
//
6668

6769
private final Function<String,HashMap<String,String>> parseWwwFormEnc = s -> {
@@ -191,6 +193,8 @@ static SimpleHttpExchange createSimpleHttpExchange(final HttpExchange exchange){
191193
cookies.put(value[0],value[1]);
192194
}
193195
}
196+
197+
outputStream = exchange.getResponseBody();
194198
}
195199

196200
//
@@ -325,6 +329,11 @@ public synchronized final HttpSession getHttpSession(){
325329
return session;
326330
}
327331

332+
@Override
333+
public final OutputStream getOutputStream(){
334+
return outputStream;
335+
}
336+
328337
//
329338

330339
@Override
@@ -343,7 +352,7 @@ public synchronized final void send(final byte[] response) throws IOException{
343352
}
344353

345354
@Override
346-
public void send(final byte[] response, final boolean gzip) throws IOException{
355+
public final void send(final byte[] response, final boolean gzip) throws IOException{
347356
send(response, HttpCode.HTTP_OK, gzip);
348357
}
349358

@@ -353,7 +362,7 @@ public synchronized final void send(final byte[] response, final int responseCod
353362
}
354363

355364
@Override
356-
public void send(final byte[] response, final int responseCode, final boolean gzip) throws IOException{
365+
public final void send(final byte[] response, final int responseCode, final boolean gzip) throws IOException{
357366
if(gzip){
358367
exchange.getResponseHeaders().set("Accept-Encoding","gzip");
359368
exchange.getResponseHeaders().set("Content-Encoding","gzip");
@@ -379,7 +388,7 @@ public synchronized final void send(final String response) throws IOException{
379388
}
380389

381390
@Override
382-
public void send(final String response, final boolean gzip) throws IOException{
391+
public final void send(final String response, final boolean gzip) throws IOException{
383392
send(response.getBytes(StandardCharsets.UTF_8), HttpCode.HTTP_OK, gzip);
384393
}
385394

@@ -389,14 +398,17 @@ public synchronized final void send(final String response, final int responseCod
389398
}
390399

391400
@Override
392-
public void send(final String response, final int responseCode, final boolean gzip) throws IOException{
401+
public final void send(final String response, final int responseCode, final boolean gzip) throws IOException{
393402
send(response.getBytes(StandardCharsets.UTF_8),responseCode,gzip);
394403
}
395404

396405
//
397406

398407
@Override
399408
public synchronized final void close(){
409+
try{
410+
outputStream.close();
411+
}catch(final IOException ignored){ }
400412
exchange.close();
401413
}
402414

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,7 @@ public final void handle(final SimpleHttpExchange exchange) throws IOException{
676676
}
677677
handle(exchange,null,null); // not found
678678
}
679+
exchange.close();
679680
}
680681

681682
/**

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

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,9 @@ public RedirectHandler(final String link){
3333

3434
@Override
3535
public final void handle(final SimpleHttpExchange exchange) throws IOException{
36-
try{
37-
System.out.println("started");
38-
exchange.getResponseHeaders().set("Location", link);
39-
exchange.send(HttpCode.HTTP_Found);
40-
}catch(final Exception e){
41-
e.printStackTrace();
42-
}
36+
exchange.getResponseHeaders().set("Location", link);
37+
exchange.send(HttpCode.HTTP_Found);
38+
exchange.close();
4339
}
4440

4541
//
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package com.kttdevelopment.simplehttpserver.handler;
2+
3+
import com.kttdevelopment.simplehttpserver.SimpleHttpExchange;
4+
import com.kttdevelopment.simplehttpserver.SimpleHttpHandler;
5+
import com.kttdevelopment.simplehttpserver.var.HttpCode;
6+
import com.kttdevelopment.simplehttpserver.var.RequestMethod;
7+
8+
import java.io.IOException;
9+
import java.io.OutputStream;
10+
import java.nio.charset.StandardCharsets;
11+
import java.util.*;
12+
import java.util.concurrent.TimeUnit;
13+
import java.util.concurrent.atomic.AtomicInteger;
14+
15+
public class SSEHandler extends SimpleHttpHandler {
16+
17+
private final List<OutputStream> listeners = new ArrayList<>();
18+
private final AtomicInteger eventId = new AtomicInteger(-1);
19+
private final LinkedList<EventStreamRecord> queue = new LinkedList<>();
20+
21+
@Override
22+
public final void handle(final SimpleHttpExchange exchange) throws IOException{
23+
exchange.getResponseHeaders().add("Access-Control-Allow-Headers", "Content-Type");
24+
if(exchange.getRequestHeaders().getFirst("origin") != null)
25+
exchange.getResponseHeaders().add("Access-Control-Allow-Origin", exchange.getRequestHeaders().getFirst("origin"));
26+
exchange.getResponseHeaders().add("Access-Control-Allow-Methods","GET, HEAD, POST, PUT, DELETE");
27+
exchange.getResponseHeaders().add("Access-Control-Max-Age", String.valueOf(TimeUnit.HOURS.toSeconds(1)));
28+
29+
if(exchange.getRequestMethod() == RequestMethod.OPTIONS){
30+
exchange.sendResponseHeaders(HttpCode.HTTP_OK,0);
31+
return;
32+
}
33+
34+
exchange.getResponseHeaders().put("content-type", Collections.singletonList("text/event-stream"));
35+
36+
int latest = 0;
37+
try{
38+
latest = Integer.parseInt(exchange.getRequestHeaders().getFirst("Last_Event-ID"));
39+
}catch(final NumberFormatException | NullPointerException ignored){ }
40+
41+
exchange.sendResponseHeaders(200,0);
42+
for(int index = latest; index < queue.size(); index++){
43+
exchange.getOutputStream().write(queue.get(index).toString(eventId.get()).getBytes(StandardCharsets.UTF_8));
44+
exchange.getOutputStream().flush();
45+
}
46+
47+
listeners.add(exchange.getOutputStream());
48+
}
49+
50+
public synchronized final void push(final String data){
51+
push(data,0,"");
52+
}
53+
54+
public synchronized final void push(final String data, final int retry, final String event){
55+
eventId.addAndGet(1);
56+
final EventStreamRecord record = new EventStreamRecord(retry,event,data);
57+
queue.add(record);
58+
listeners.forEach(stream -> {
59+
try{
60+
stream.write(record.toString(eventId.get()).getBytes(StandardCharsets.UTF_8));
61+
stream.flush();
62+
}catch(final IOException ignored){ }
63+
});
64+
}
65+
66+
private static class EventStreamRecord {
67+
68+
private final int retry;
69+
private final String event;
70+
private final String data;
71+
72+
public EventStreamRecord(final int retry, final String event, final String data){
73+
this.retry = retry;
74+
this.event = event;
75+
this.data = data;
76+
}
77+
78+
public final String toString(final int id){
79+
return
80+
"id: " + id + '\n' +
81+
(retry > 0 ? "retry: " + retry + '\n' : "") +
82+
(!event.isBlank() ? "event: " + event + '\n' : "") +
83+
(!data.isBlank() ? "data: " + data + '\n' : "") +
84+
'\n';
85+
}
86+
87+
}
88+
89+
}

0 commit comments

Comments
 (0)