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

Commit 103c135

Browse files
committed
Implement SimpleHttpsServer
1 parent c836eb5 commit 103c135

2 files changed

Lines changed: 300 additions & 0 deletions

File tree

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,21 @@ public static SimpleHttpsServer create(final int port, final int backlog) throws
7878
return SimpleHttpsServerImpl.create(port,backlog);
7979
}
8080

81+
//
82+
83+
/**
84+
* Returns the native https server.
85+
*
86+
* @return https server
87+
*
88+
* @see HttpsServer
89+
* @since 03.04.00
90+
* @author Ktt Development
91+
*/
92+
@Override
93+
public abstract HttpsServer getHttpServer();
94+
95+
8196
//
8297

8398
/**
Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
1+
package com.kttdevelopment.simplehttpserver;
2+
3+
import com.kttdevelopment.simplehttpserver.handler.RootHandler;
4+
import com.sun.net.httpserver.*;
5+
6+
import java.io.IOException;
7+
import java.net.InetSocketAddress;
8+
import java.util.*;
9+
import java.util.concurrent.Executor;
10+
11+
/**
12+
* Implementation for {@link SimpleHttpsServer}. Applications do not use this class.
13+
*
14+
* @see SimpleHttpsServer
15+
* @since 03.04.00
16+
* @version 03.04.00
17+
* @author Ktt Development
18+
*/
19+
final public class SimpleHttpsServerImpl extends SimpleHttpsServer {
20+
21+
private final HttpsServer server = HttpsServer.create();
22+
23+
private HttpSessionHandler sessionHandler;
24+
25+
private final Map<HttpContext, HttpHandler> contexts = new HashMap<>();
26+
27+
private boolean running = false;
28+
29+
/**
30+
* Creates a {@link SimpleHttpServer}.
31+
*
32+
* @param port port to run the server on
33+
* @param backlog how many requests to backlog
34+
* @return a {@link SimpleHttpServer}
35+
* @throws java.net.BindException if server can not bind to port
36+
* @throws IOException uncaught exception
37+
*
38+
* @see SimpleHttpServer
39+
* @since 03.04.00
40+
* @author Ktt Development
41+
*/
42+
static SimpleHttpsServer create(final Integer port, final Integer backlog) throws IOException{
43+
return new SimpleHttpsServerImpl(port,backlog);
44+
}
45+
46+
SimpleHttpsServerImpl(final Integer port, final Integer backlog) throws IOException{
47+
if(port != null)
48+
server.bind(new InetSocketAddress(port), backlog != null ? backlog : 0);
49+
}
50+
51+
private void handle(final HttpExchange exchange){
52+
if(sessionHandler != null)
53+
sessionHandler.getSession(exchange).updateLastAccessTime();
54+
}
55+
56+
//
57+
58+
@Override
59+
public final HttpsServer getHttpServer(){
60+
return server;
61+
}
62+
63+
//
64+
65+
@Override
66+
public final void setHttpsConfigurator(final HttpsConfigurator config){
67+
server.setHttpsConfigurator(config);
68+
}
69+
70+
@Override
71+
public final HttpsConfigurator getHttpsConfigurator(){
72+
return server.getHttpsConfigurator();
73+
}
74+
75+
// region copySimpleHttpServerImpl
76+
77+
@Override
78+
public synchronized final InetSocketAddress bind(final int port) throws IOException{
79+
final InetSocketAddress addr = new InetSocketAddress(port);
80+
server.bind(addr, 0);
81+
return addr;
82+
}
83+
84+
@Override
85+
public synchronized final InetSocketAddress bind(final int port, final int backlog) throws IOException{
86+
final InetSocketAddress addr = new InetSocketAddress(port);
87+
server.bind(addr, backlog);
88+
return addr;
89+
}
90+
91+
@Override
92+
public synchronized final void bind(final InetSocketAddress addr) throws IOException{
93+
server.bind(addr,0);
94+
}
95+
96+
@Override
97+
public synchronized final void bind(final InetSocketAddress addr, final int backlog) throws IOException{
98+
server.bind(addr,backlog);
99+
}
100+
101+
//
102+
103+
@Override
104+
public final InetSocketAddress getAddress(){
105+
return server.getAddress();
106+
}
107+
108+
//
109+
110+
@Override
111+
public synchronized final void setExecutor(final Executor executor){
112+
server.setExecutor(executor);
113+
}
114+
115+
@Override
116+
public final Executor getExecutor(){
117+
return server.getExecutor();
118+
}
119+
120+
@Override
121+
public synchronized final void setHttpSessionHandler(final HttpSessionHandler sessionHandler){
122+
this.sessionHandler = sessionHandler;
123+
}
124+
125+
@Override
126+
public final HttpSessionHandler getHttpSessionHandler(){
127+
return sessionHandler;
128+
}
129+
130+
@Override
131+
public final HttpSession getHttpSession(final HttpExchange exchange){
132+
return sessionHandler != null ? sessionHandler.getSession(exchange) : null;
133+
}
134+
135+
@Override
136+
public final HttpSession getHttpSession(final SimpleHttpExchange exchange){
137+
return getHttpSession(exchange.getHttpExchange());
138+
}
139+
140+
//
141+
142+
@Override
143+
public synchronized final HttpContext createContext(final String path){
144+
return createContext(path,(HttpExchange exchange) -> {});
145+
}
146+
147+
@Override
148+
public synchronized final HttpContext createContext(final String path, final HttpHandler handler){
149+
if(!getContext(path).equals("/") && handler instanceof RootHandler)
150+
throw new IllegalArgumentException("RootHandler can only be used at the root '/' context");
151+
152+
final HttpHandler wrapper = exchange -> {
153+
handle(exchange);
154+
handler.handle(exchange);
155+
};
156+
final HttpContext context = server.createContext(getContext(path),wrapper);
157+
158+
contexts.put(context,handler);
159+
160+
return context;
161+
}
162+
163+
//
164+
165+
@Override
166+
public synchronized final HttpContext createContext(final String path, final Authenticator authenticator){
167+
final HttpContext context = createContext(path);
168+
context.setAuthenticator(authenticator);
169+
return context;
170+
}
171+
172+
@Override
173+
public synchronized final HttpContext createContext(final String path, final HttpHandler handler, final Authenticator authenticator){
174+
final HttpContext context = createContext(path,handler);
175+
context.setAuthenticator(authenticator);
176+
return context;
177+
}
178+
179+
//
180+
181+
@Override
182+
public synchronized final void removeContext(final String path){
183+
server.removeContext(getContext(path));
184+
for(final HttpContext context : contexts.keySet()){
185+
if(context.getPath().equalsIgnoreCase(getContext(path))){
186+
contexts.remove(context);
187+
break;
188+
}
189+
}
190+
}
191+
192+
@Override
193+
public synchronized final void removeContext(final HttpContext context){
194+
contexts.remove(context);
195+
server.removeContext(context);
196+
}
197+
198+
//
199+
200+
@Override
201+
public final HttpHandler getContextHandler(final String path){
202+
for(final HttpContext context : contexts.keySet())
203+
if(context.getPath().equals(getContext(path)))
204+
return context.getHandler();
205+
return null;
206+
}
207+
208+
@Override
209+
public final HttpHandler getContextHandler(final HttpContext context){
210+
return contexts.get(context);
211+
}
212+
213+
@Override
214+
public final Map<HttpContext, HttpHandler> getContexts(){
215+
return new HashMap<>(contexts);
216+
}
217+
218+
//
219+
220+
@Override
221+
public synchronized final String getRandomContext(){
222+
return getRandomContext("");
223+
}
224+
225+
@Override
226+
public synchronized final String getRandomContext(final String context){
227+
String targetContext;
228+
229+
final String head = context.isEmpty() ? "" : getContext(context);
230+
231+
do targetContext = head + getContext(UUID.randomUUID().toString());
232+
while(getContextHandler(targetContext) != null);
233+
234+
return targetContext;
235+
}
236+
237+
238+
//
239+
240+
@Override
241+
public synchronized final void start(){
242+
if(!running){
243+
server.start();
244+
running = true;
245+
}
246+
}
247+
248+
@Override
249+
public synchronized final void stop(){
250+
stop(0);
251+
}
252+
253+
@Override
254+
public synchronized final void stop(final int delay){
255+
if(running){
256+
running = false;
257+
server.stop(delay);
258+
}
259+
}
260+
261+
// endregion
262+
263+
@SuppressWarnings("StringBufferReplaceableByString")
264+
@Override
265+
public String toString(){
266+
final StringBuilder OUT = new StringBuilder();
267+
OUT.append("SimpleHttpsServer") .append('{');
268+
OUT.append("httpServer") .append('=') .append(server) .append(", ");
269+
OUT.append("httpsConfigurator") .append('=') .append(getHttpsConfigurator()) .append(", ");
270+
OUT.append("contexts") .append('=') .append(contexts) .append(", ");
271+
OUT.append("address") .append('=') .append(getAddress()) .append(", ");
272+
OUT.append("executor") .append('=') .append(getExecutor());
273+
OUT.append('}');
274+
return OUT.toString();
275+
}
276+
277+
// start slash; no end slash
278+
private static String getContext(final String path){
279+
final String linSlash = path.replace("\\","/");
280+
if(linSlash.equals("/")) return "/";
281+
final String seSlash = (!linSlash.startsWith("/") ? "/" : "") + linSlash + (!linSlash.endsWith("/") ? "/" : "");
282+
return seSlash.substring(0,seSlash.length()-1);
283+
}
284+
285+
}

0 commit comments

Comments
 (0)