Skip to content

Commit b3639a4

Browse files
SentryManmechite
andcommitted
start
Co-Authored-By: Mahied Maruf <[email protected]>
1 parent 06b5696 commit b3639a4

File tree

20 files changed

+767
-59
lines changed

20 files changed

+767
-59
lines changed

avaje-jex-http3-flupke/pom.xml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0"
2+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
<parent>
6+
<groupId>io.avaje</groupId>
7+
<artifactId>avaje-jex-parent</artifactId>
8+
<version>3.3</version>
9+
</parent>
10+
<artifactId>avaje-jex-http3-flupke</artifactId>
11+
<version>0.1</version>
12+
<properties>
13+
<maven.compiler.source>26</maven.compiler.source>
14+
<maven.compiler.release>21</maven.compiler.release>
15+
</properties>
16+
<dependencies>
17+
<dependency>
18+
<groupId>tech.kwik</groupId>
19+
<artifactId>flupke</artifactId>
20+
<version>0.9</version>
21+
</dependency>
22+
<dependency>
23+
<groupId>tech.kwik</groupId>
24+
<artifactId>kwik</artifactId>
25+
<version>0.10.7</version>
26+
</dependency>
27+
<dependency>
28+
<groupId>tech.kwik</groupId>
29+
<artifactId>kwik-qlog</artifactId>
30+
<version>0.10.7</version>
31+
</dependency>
32+
<dependency>
33+
<groupId>io.avaje</groupId>
34+
<artifactId>avaje-jex-ssl</artifactId>
35+
</dependency>
36+
<dependency>
37+
<groupId>io.avaje</groupId>
38+
<artifactId>avaje-jex-test</artifactId>
39+
<scope>test</scope>
40+
</dependency>
41+
</dependencies>
42+
</project>
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package io.avaje.jex.http3.flupke;
2+
3+
import java.net.DatagramSocket;
4+
import java.util.Map;
5+
import java.util.function.Consumer;
6+
7+
import io.avaje.jex.Jex;
8+
import io.avaje.jex.http3.flupke.impl.H3ServerProvider;
9+
import io.avaje.jex.spi.JexPlugin;
10+
import tech.kwik.core.server.ServerConnector.Builder;
11+
import tech.kwik.flupke.server.Http3ServerExtensionFactory;
12+
13+
public final class FlupkeJexPlugin implements JexPlugin {
14+
15+
private DatagramSocket socket;
16+
private Map<String, Http3ServerExtensionFactory> extensions = Map.of();
17+
private Consumer<Builder> consumer = b -> {};
18+
19+
private FlupkeJexPlugin() {}
20+
21+
public static FlupkeJexPlugin create() {
22+
return new FlupkeJexPlugin();
23+
}
24+
25+
public FlupkeJexPlugin customSocket(DatagramSocket socket) {
26+
this.socket = socket;
27+
return this;
28+
}
29+
30+
public FlupkeJexPlugin extensions(Map<String, Http3ServerExtensionFactory> extensions) {
31+
this.extensions = extensions;
32+
return this;
33+
}
34+
35+
public FlupkeJexPlugin config(Consumer<Builder> consumer) {
36+
this.consumer = consumer;
37+
return this;
38+
}
39+
40+
@Override
41+
public void apply(Jex jex) {
42+
jex.config().serverProvider(new H3ServerProvider(consumer, extensions, socket));
43+
}
44+
}
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
package io.avaje.jex.http3.flupke.impl;
2+
3+
import java.io.IOException;
4+
import java.io.InputStream;
5+
import java.io.OutputStream;
6+
import java.io.UncheckedIOException;
7+
import java.net.InetSocketAddress;
8+
import java.net.URI;
9+
import java.net.http.HttpHeaders;
10+
11+
import com.sun.net.httpserver.Headers;
12+
import com.sun.net.httpserver.HttpContext;
13+
import com.sun.net.httpserver.HttpExchange;
14+
import com.sun.net.httpserver.HttpPrincipal;
15+
16+
import tech.kwik.flupke.server.HttpServerRequest;
17+
import tech.kwik.flupke.server.HttpServerResponse;
18+
19+
class FlupkeExchange extends HttpExchange {
20+
21+
private final HttpServerRequest request;
22+
private final HttpServerResponse response;
23+
24+
private final Headers responseHeaders = new Headers();
25+
private Headers requestHeaders;
26+
private HttpContext ctx;
27+
private int statusCode = 0;
28+
private InputStream is;
29+
private PlaceholderOutputStream os = new PlaceholderOutputStream();
30+
31+
public FlupkeExchange(HttpServerRequest request, HttpServerResponse response, HttpContext ctx) {
32+
this.request = request;
33+
this.response = response;
34+
this.ctx = ctx;
35+
this.is = request.body();
36+
}
37+
38+
@Override
39+
public Headers getRequestHeaders() {
40+
if (requestHeaders == null) {
41+
requestHeaders = new Headers(request.headers().map());
42+
}
43+
return requestHeaders;
44+
}
45+
46+
@Override
47+
public Headers getResponseHeaders() {
48+
return responseHeaders;
49+
}
50+
51+
@Override
52+
public URI getRequestURI() {
53+
return URI.create(request.path());
54+
}
55+
56+
@Override
57+
public String getRequestMethod() {
58+
return request.method();
59+
}
60+
61+
@Override
62+
public HttpContext getHttpContext() {
63+
return ctx;
64+
}
65+
66+
@Override
67+
public void close() {
68+
try (var __ = is;
69+
var ___ = response.getOutputStream(); ) {
70+
} catch (IOException e) {
71+
throw new UncheckedIOException(e);
72+
}
73+
}
74+
75+
@Override
76+
public InputStream getRequestBody() {
77+
return is;
78+
}
79+
80+
@Override
81+
public OutputStream getResponseBody() {
82+
return os;
83+
}
84+
85+
@Override
86+
public void sendResponseHeaders(int rCode, long responseLength) throws IOException {
87+
statusCode = rCode;
88+
response.setHeaders(HttpHeaders.of(responseHeaders, (a, b) -> true));
89+
response.setStatus(rCode);
90+
os.wrapped = response.getOutputStream();
91+
}
92+
93+
@Override
94+
public InetSocketAddress getRemoteAddress() {
95+
return null;
96+
}
97+
98+
@Override
99+
public int getResponseCode() {
100+
return statusCode;
101+
}
102+
103+
@Override
104+
public InetSocketAddress getLocalAddress() {
105+
return null;
106+
}
107+
108+
@Override
109+
public String getProtocol() {
110+
111+
return "h3";
112+
}
113+
114+
@Override
115+
public Object getAttribute(String name) {
116+
throw new UnsupportedOperationException();
117+
}
118+
119+
@Override
120+
public void setAttribute(String name, Object value) {
121+
throw new UnsupportedOperationException();
122+
}
123+
124+
@Override
125+
public void setStreams(InputStream i, OutputStream o) {
126+
is = i;
127+
os.wrapped = o;
128+
}
129+
130+
@Override
131+
public HttpPrincipal getPrincipal() {
132+
throw new UnsupportedOperationException();
133+
}
134+
135+
/**
136+
* An OutputStream which wraps another stream which is supplied either at creation time, or
137+
* sometime later. If a caller/user tries to write to this stream before the wrapped stream has
138+
* been provided, then an IOException will be thrown.
139+
*/
140+
class PlaceholderOutputStream extends OutputStream {
141+
142+
OutputStream wrapped;
143+
144+
void setWrappedStream(OutputStream os) {
145+
wrapped = os;
146+
}
147+
148+
boolean isWrapped() {
149+
return wrapped != null;
150+
}
151+
152+
private void checkWrap() throws IOException {
153+
if (wrapped == null) {
154+
throw new IOException("response headers not sent yet");
155+
}
156+
}
157+
158+
@Override
159+
public void write(int b) throws IOException {
160+
checkWrap();
161+
wrapped.write(b);
162+
}
163+
164+
@Override
165+
public void write(byte b[]) throws IOException {
166+
checkWrap();
167+
wrapped.write(b);
168+
}
169+
170+
@Override
171+
public void write(byte b[], int off, int len) throws IOException {
172+
checkWrap();
173+
wrapped.write(b, off, len);
174+
}
175+
176+
@Override
177+
public void flush() throws IOException {
178+
checkWrap();
179+
wrapped.flush();
180+
}
181+
182+
@Override
183+
public void close() throws IOException {
184+
checkWrap();
185+
wrapped.close();
186+
}
187+
}
188+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package io.avaje.jex.http3.flupke.impl;
2+
3+
import java.util.ArrayList;
4+
import java.util.HashMap;
5+
import java.util.List;
6+
import java.util.Map;
7+
8+
import com.sun.net.httpserver.Authenticator;
9+
import com.sun.net.httpserver.Filter;
10+
import com.sun.net.httpserver.HttpContext;
11+
import com.sun.net.httpserver.HttpHandler;
12+
import com.sun.net.httpserver.HttpServer;
13+
14+
class FlupkeHttpContext extends HttpContext {
15+
16+
private final HttpSpiContextHandler jettyContextHandler;
17+
18+
private final HttpServer _server;
19+
20+
private final Map<String, Object> _attributes = new HashMap<>();
21+
22+
private final List<Filter> _filters = new ArrayList<>();
23+
24+
private Authenticator _authenticator;
25+
26+
private HttpHandler httpHandler;
27+
28+
protected FlupkeHttpContext(HttpServer server, String contextPath, HttpHandler handler) {
29+
httpHandler = handler;
30+
this._server = server;
31+
jettyContextHandler = new HttpSpiContextHandler(this, handler);
32+
}
33+
34+
protected HttpSpiContextHandler flupkeHandler() {
35+
return jettyContextHandler;
36+
}
37+
38+
@Override
39+
public HttpHandler getHandler() {
40+
return httpHandler;
41+
}
42+
43+
@Override
44+
public void setHandler(HttpHandler h) {
45+
jettyContextHandler.setHttpHandler(h);
46+
}
47+
48+
@Override
49+
public String getPath() {
50+
return "/";
51+
}
52+
53+
@Override
54+
public HttpServer getServer() {
55+
return _server;
56+
}
57+
58+
@Override
59+
public Map<String, Object> getAttributes() {
60+
return _attributes;
61+
}
62+
63+
@Override
64+
public List<Filter> getFilters() {
65+
return _filters;
66+
}
67+
68+
@Override
69+
public Authenticator setAuthenticator(Authenticator auth) {
70+
Authenticator previous = _authenticator;
71+
_authenticator = auth;
72+
return previous;
73+
}
74+
75+
@Override
76+
public Authenticator getAuthenticator() {
77+
return _authenticator;
78+
}
79+
}

0 commit comments

Comments
 (0)