1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package org.apache.hc.core5.http.impl.bootstrap;
28
29 import java.net.InetAddress;
30 import java.util.ArrayList;
31 import java.util.List;
32
33 import javax.net.ServerSocketFactory;
34 import javax.net.ssl.SSLContext;
35 import javax.net.ssl.SSLParameters;
36 import javax.net.ssl.SSLServerSocketFactory;
37
38 import org.apache.hc.core5.function.Callback;
39 import org.apache.hc.core5.function.Supplier;
40 import org.apache.hc.core5.http.ClassicHttpResponse;
41 import org.apache.hc.core5.http.ConnectionReuseStrategy;
42 import org.apache.hc.core5.http.ExceptionListener;
43 import org.apache.hc.core5.http.HttpResponseFactory;
44 import org.apache.hc.core5.http.URIScheme;
45 import org.apache.hc.core5.http.config.CharCodingConfig;
46 import org.apache.hc.core5.http.config.Http1Config;
47 import org.apache.hc.core5.http.config.NamedElementChain;
48 import org.apache.hc.core5.http.impl.DefaultConnectionReuseStrategy;
49 import org.apache.hc.core5.http.impl.Http1StreamListener;
50 import org.apache.hc.core5.http.impl.HttpProcessors;
51 import org.apache.hc.core5.http.impl.io.DefaultBHttpServerConnection;
52 import org.apache.hc.core5.http.impl.io.DefaultBHttpServerConnectionFactory;
53 import org.apache.hc.core5.http.impl.io.DefaultClassicHttpResponseFactory;
54 import org.apache.hc.core5.http.impl.io.HttpService;
55 import org.apache.hc.core5.http.io.HttpConnectionFactory;
56 import org.apache.hc.core5.http.io.HttpFilterHandler;
57 import org.apache.hc.core5.http.io.HttpRequestHandler;
58 import org.apache.hc.core5.http.io.HttpServerRequestHandler;
59 import org.apache.hc.core5.http.io.SocketConfig;
60 import org.apache.hc.core5.http.io.ssl.DefaultTlsSetupHandler;
61 import org.apache.hc.core5.http.io.support.BasicHttpServerExpectationDecorator;
62 import org.apache.hc.core5.http.io.support.BasicHttpServerRequestHandler;
63 import org.apache.hc.core5.http.io.support.HttpServerExpectationFilter;
64 import org.apache.hc.core5.http.io.support.HttpServerFilterChainElement;
65 import org.apache.hc.core5.http.io.support.HttpServerFilterChainRequestHandler;
66 import org.apache.hc.core5.http.io.support.TerminalServerFilter;
67 import org.apache.hc.core5.http.protocol.HttpProcessor;
68 import org.apache.hc.core5.http.protocol.LookupRegistry;
69 import org.apache.hc.core5.http.protocol.RequestHandlerRegistry;
70 import org.apache.hc.core5.http.protocol.UriPatternType;
71 import org.apache.hc.core5.net.InetAddressUtils;
72 import org.apache.hc.core5.util.Args;
73
74
75
76
77
78
79 public class ServerBootstrap {
80
81 private final List<HandlerEntry<HttpRequestHandler>> handlerList;
82 private final List<FilterEntry<HttpFilterHandler>> filters;
83 private String canonicalHostName;
84 private LookupRegistry<HttpRequestHandler> lookupRegistry;
85 private int listenerPort;
86 private InetAddress localAddress;
87 private SocketConfig socketConfig;
88 private Http1Config http1Config;
89 private CharCodingConfig charCodingConfig;
90 private HttpProcessor httpProcessor;
91 private ConnectionReuseStrategy connStrategy;
92 private HttpResponseFactory<ClassicHttpResponse> responseFactory;
93 private ServerSocketFactory serverSocketFactory;
94 private SSLContext sslContext;
95 private Callback<SSLParameters> sslSetupHandler;
96 private HttpConnectionFactory<? extends DefaultBHttpServerConnection> connectionFactory;
97 private ExceptionListener exceptionListener;
98 private Http1StreamListener streamListener;
99
100 private ServerBootstrap() {
101 this.handlerList = new ArrayList<>();
102 this.filters = new ArrayList<>();
103 }
104
105 public static ServerBootstrap bootstrap() {
106 return new ServerBootstrap();
107 }
108
109
110
111
112
113
114 public final ServerBootstrap setCanonicalHostName(final String canonicalHostName) {
115 this.canonicalHostName = canonicalHostName;
116 return this;
117 }
118
119
120
121
122 public final ServerBootstrap setListenerPort(final int listenerPort) {
123 this.listenerPort = listenerPort;
124 return this;
125 }
126
127
128
129
130 public final ServerBootstrap setLocalAddress(final InetAddress localAddress) {
131 this.localAddress = localAddress;
132 return this;
133 }
134
135
136
137
138 public final ServerBootstrap setSocketConfig(final SocketConfig socketConfig) {
139 this.socketConfig = socketConfig;
140 return this;
141 }
142
143
144
145
146 public final ServerBootstrap setHttp1Config(final Http1Config http1Config) {
147 this.http1Config = http1Config;
148 return this;
149 }
150
151
152
153
154 public final ServerBootstrap setCharCodingConfig(final CharCodingConfig charCodingConfig) {
155 this.charCodingConfig = charCodingConfig;
156 return this;
157 }
158
159
160
161
162 public final ServerBootstrap setHttpProcessor(final HttpProcessor httpProcessor) {
163 this.httpProcessor = httpProcessor;
164 return this;
165 }
166
167
168
169
170 public final ServerBootstrap setConnectionReuseStrategy(final ConnectionReuseStrategy connStrategy) {
171 this.connStrategy = connStrategy;
172 return this;
173 }
174
175
176
177
178 public final ServerBootstrap setResponseFactory(final HttpResponseFactory<ClassicHttpResponse> responseFactory) {
179 this.responseFactory = responseFactory;
180 return this;
181 }
182
183
184
185
186 public final ServerBootstrap setLookupRegistry(final LookupRegistry<HttpRequestHandler> lookupRegistry) {
187 this.lookupRegistry = lookupRegistry;
188 return this;
189 }
190
191
192
193
194
195
196
197
198 public final ServerBootstrap register(final String uriPattern, final HttpRequestHandler requestHandler) {
199 Args.notBlank(uriPattern, "URI pattern");
200 Args.notNull(requestHandler, "Supplier");
201 handlerList.add(new HandlerEntry<>(null, uriPattern, requestHandler));
202 return this;
203 }
204
205
206
207
208
209
210
211
212
213 public final ServerBootstrap registerVirtual(final String hostname, final String uriPattern, final HttpRequestHandler requestHandler) {
214 Args.notBlank(hostname, "Hostname");
215 Args.notBlank(uriPattern, "URI pattern");
216 Args.notNull(requestHandler, "Supplier");
217 handlerList.add(new HandlerEntry<>(hostname, uriPattern, requestHandler));
218 return this;
219 }
220
221
222
223
224 public final ServerBootstrap setConnectionFactory(
225 final HttpConnectionFactory<? extends DefaultBHttpServerConnection> connectionFactory) {
226 this.connectionFactory = connectionFactory;
227 return this;
228 }
229
230
231
232
233 public final ServerBootstrap setServerSocketFactory(final ServerSocketFactory serverSocketFactory) {
234 this.serverSocketFactory = serverSocketFactory;
235 return this;
236 }
237
238
239
240
241
242
243
244 public final ServerBootstrap setSslContext(final SSLContext sslContext) {
245 this.sslContext = sslContext;
246 return this;
247 }
248
249
250
251
252 public final ServerBootstrap setSslSetupHandler(final Callback<SSLParameters> sslSetupHandler) {
253 this.sslSetupHandler = sslSetupHandler;
254 return this;
255 }
256
257
258
259
260 public final ServerBootstrap setExceptionListener(final ExceptionListener exceptionListener) {
261 this.exceptionListener = exceptionListener;
262 return this;
263 }
264
265
266
267
268 public final ServerBootstrap setStreamListener(final Http1StreamListener streamListener) {
269 this.streamListener = streamListener;
270 return this;
271 }
272
273
274
275
276 public final ServerBootstrap addFilterBefore(final String existing, final String name, final HttpFilterHandler filterHandler) {
277 Args.notBlank(existing, "Existing");
278 Args.notBlank(name, "Name");
279 Args.notNull(filterHandler, "Filter handler");
280 filters.add(new FilterEntry<>(FilterEntry.Postion.BEFORE, name, filterHandler, existing));
281 return this;
282 }
283
284
285
286
287 public final ServerBootstrap addFilterAfter(final String existing, final String name, final HttpFilterHandler filterHandler) {
288 Args.notBlank(existing, "Existing");
289 Args.notBlank(name, "Name");
290 Args.notNull(filterHandler, "Filter handler");
291 filters.add(new FilterEntry<>(FilterEntry.Postion.AFTER, name, filterHandler, existing));
292 return this;
293 }
294
295
296
297
298 public final ServerBootstrap replaceFilter(final String existing, final HttpFilterHandler filterHandler) {
299 Args.notBlank(existing, "Existing");
300 Args.notNull(filterHandler, "Filter handler");
301 filters.add(new FilterEntry<>(FilterEntry.Postion.REPLACE, existing, filterHandler, existing));
302 return this;
303 }
304
305
306
307
308 public final ServerBootstrap addFilterFirst(final String name, final HttpFilterHandler filterHandler) {
309 Args.notNull(name, "Name");
310 Args.notNull(filterHandler, "Filter handler");
311 filters.add(new FilterEntry<>(FilterEntry.Postion.FIRST, name, filterHandler, null));
312 return this;
313 }
314
315
316
317
318 public final ServerBootstrap addFilterLast(final String name, final HttpFilterHandler filterHandler) {
319 Args.notNull(name, "Name");
320 Args.notNull(filterHandler, "Filter handler");
321 filters.add(new FilterEntry<>(FilterEntry.Postion.LAST, name, filterHandler, null));
322 return this;
323 }
324
325 public HttpServer create() {
326 final RequestHandlerRegistry<HttpRequestHandler> handlerRegistry = new RequestHandlerRegistry<>(
327 canonicalHostName != null ? canonicalHostName : InetAddressUtils.getCanonicalLocalHostName(),
328 new Supplier<LookupRegistry<HttpRequestHandler>>() {
329
330 @Override
331 public LookupRegistry<HttpRequestHandler> get() {
332 return lookupRegistry != null ? lookupRegistry :
333 UriPatternType.<HttpRequestHandler>newMatcher(UriPatternType.URI_PATTERN);
334 }
335
336 });
337 for (final HandlerEntry<HttpRequestHandler> entry: handlerList) {
338 handlerRegistry.register(entry.hostname, entry.uriPattern, entry.handler);
339 }
340
341 final HttpServerRequestHandler requestHandler;
342 if (!filters.isEmpty()) {
343 final NamedElementChain<HttpFilterHandler> filterChainDefinition = new NamedElementChain<>();
344 filterChainDefinition.addLast(
345 new TerminalServerFilter(
346 handlerRegistry,
347 this.responseFactory != null ? this.responseFactory : DefaultClassicHttpResponseFactory.INSTANCE),
348 StandardFilter.MAIN_HANDLER.name());
349 filterChainDefinition.addFirst(
350 new HttpServerExpectationFilter(),
351 StandardFilter.EXPECT_CONTINUE.name());
352
353 for (final FilterEntry<HttpFilterHandler> entry: filters) {
354 switch (entry.postion) {
355 case AFTER:
356 filterChainDefinition.addAfter(entry.existing, entry.filterHandler, entry.name);
357 break;
358 case BEFORE:
359 filterChainDefinition.addBefore(entry.existing, entry.filterHandler, entry.name);
360 break;
361 case REPLACE:
362 filterChainDefinition.replace(entry.existing, entry.filterHandler);
363 break;
364 case FIRST:
365 filterChainDefinition.addFirst(entry.filterHandler, entry.name);
366 break;
367 case LAST:
368
369
370 filterChainDefinition.addBefore(StandardFilter.MAIN_HANDLER.name(), entry.filterHandler, entry.name);
371 break;
372 }
373 }
374
375 NamedElementChain<HttpFilterHandler>.Node current = filterChainDefinition.getLast();
376 HttpServerFilterChainElement filterChain = null;
377 while (current != null) {
378 filterChain = new HttpServerFilterChainElement(current.getValue(), filterChain);
379 current = current.getPrevious();
380 }
381 requestHandler = new HttpServerFilterChainRequestHandler(filterChain);
382 } else {
383 requestHandler = new BasicHttpServerExpectationDecorator(new BasicHttpServerRequestHandler(
384 handlerRegistry,
385 this.responseFactory != null ? this.responseFactory : DefaultClassicHttpResponseFactory.INSTANCE));
386 }
387
388 final HttpService/io/HttpService.html#HttpService">HttpService httpService = new HttpService(
389 this.httpProcessor != null ? this.httpProcessor : HttpProcessors.server(),
390 requestHandler,
391 this.connStrategy != null ? this.connStrategy : DefaultConnectionReuseStrategy.INSTANCE,
392 this.streamListener);
393
394 ServerSocketFactory serverSocketFactoryCopy = this.serverSocketFactory;
395 if (serverSocketFactoryCopy == null) {
396 if (this.sslContext != null) {
397 serverSocketFactoryCopy = this.sslContext.getServerSocketFactory();
398 } else {
399 serverSocketFactoryCopy = ServerSocketFactory.getDefault();
400 }
401 }
402
403 HttpConnectionFactory<? extends DefaultBHttpServerConnection> connectionFactoryCopy = this.connectionFactory;
404 if (connectionFactoryCopy == null) {
405 final String scheme = serverSocketFactoryCopy instanceof SSLServerSocketFactory ? URIScheme.HTTPS.id : URIScheme.HTTP.id;
406 connectionFactoryCopy = new DefaultBHttpServerConnectionFactory(scheme, this.http1Config, this.charCodingConfig);
407 }
408
409 return new HttpServer(
410 this.listenerPort > 0 ? this.listenerPort : 0,
411 httpService,
412 this.localAddress,
413 this.socketConfig != null ? this.socketConfig : SocketConfig.DEFAULT,
414 serverSocketFactoryCopy,
415 connectionFactoryCopy,
416 sslSetupHandler != null ? sslSetupHandler : new DefaultTlsSetupHandler(),
417 this.exceptionListener != null ? this.exceptionListener : ExceptionListener.NO_OP);
418 }
419
420 }