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.util.ArrayList;
30 import java.util.List;
31
32 import org.apache.hc.core5.function.Callback;
33 import org.apache.hc.core5.function.Decorator;
34 import org.apache.hc.core5.function.Supplier;
35 import org.apache.hc.core5.http.ConnectionReuseStrategy;
36 import org.apache.hc.core5.http.HttpRequestMapper;
37 import org.apache.hc.core5.http.config.CharCodingConfig;
38 import org.apache.hc.core5.http.config.Http1Config;
39 import org.apache.hc.core5.http.config.NamedElementChain;
40 import org.apache.hc.core5.http.impl.DefaultConnectionReuseStrategy;
41 import org.apache.hc.core5.http.impl.DefaultContentLengthStrategy;
42 import org.apache.hc.core5.http.impl.Http1StreamListener;
43 import org.apache.hc.core5.http.impl.HttpProcessors;
44 import org.apache.hc.core5.http.impl.nio.DefaultHttpRequestParserFactory;
45 import org.apache.hc.core5.http.impl.nio.DefaultHttpResponseWriterFactory;
46 import org.apache.hc.core5.http.impl.nio.ServerHttp1IOEventHandlerFactory;
47 import org.apache.hc.core5.http.impl.nio.ServerHttp1StreamDuplexerFactory;
48 import org.apache.hc.core5.http.impl.routing.RequestRouter;
49 import org.apache.hc.core5.http.nio.AsyncFilterHandler;
50 import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
51 import org.apache.hc.core5.http.nio.AsyncServerRequestHandler;
52 import org.apache.hc.core5.http.nio.HandlerFactory;
53 import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
54 import org.apache.hc.core5.http.nio.support.AsyncServerExpectationFilter;
55 import org.apache.hc.core5.http.nio.support.AsyncServerFilterChainElement;
56 import org.apache.hc.core5.http.nio.support.AsyncServerFilterChainExchangeHandlerFactory;
57 import org.apache.hc.core5.http.nio.support.BasicAsyncServerExpectationDecorator;
58 import org.apache.hc.core5.http.nio.support.BasicServerExchangeHandler;
59 import org.apache.hc.core5.http.nio.support.DefaultAsyncResponseExchangeHandlerFactory;
60 import org.apache.hc.core5.http.nio.support.TerminalAsyncServerFilter;
61 import org.apache.hc.core5.http.protocol.HttpProcessor;
62 import org.apache.hc.core5.http.protocol.UriPatternType;
63 import org.apache.hc.core5.net.InetAddressUtils;
64 import org.apache.hc.core5.net.URIAuthority;
65 import org.apache.hc.core5.reactor.IOEventHandlerFactory;
66 import org.apache.hc.core5.reactor.IOReactorConfig;
67 import org.apache.hc.core5.reactor.IOSession;
68 import org.apache.hc.core5.reactor.IOSessionListener;
69 import org.apache.hc.core5.util.Args;
70 import org.apache.hc.core5.util.Timeout;
71
72
73
74
75
76
77 @SuppressWarnings("deprecation")
78 public class AsyncServerBootstrap {
79
80 private final List<RequestRouter.Entry<Supplier<AsyncServerExchangeHandler>>> routeEntries;
81 private final List<FilterEntry<AsyncFilterHandler>> filters;
82 private String canonicalHostName;
83 private HttpRequestMapper<Supplier<AsyncServerExchangeHandler>> requestRouter;
84 private org.apache.hc.core5.http.protocol.LookupRegistry<Supplier<AsyncServerExchangeHandler>> lookupRegistry;
85 private IOReactorConfig ioReactorConfig;
86 private Http1Config http1Config;
87 private CharCodingConfig charCodingConfig;
88 private HttpProcessor httpProcessor;
89 private ConnectionReuseStrategy connStrategy;
90 private TlsStrategy tlsStrategy;
91 private Timeout handshakeTimeout;
92 private Decorator<IOSession> ioSessionDecorator;
93 private Callback<Exception> exceptionCallback;
94 private IOSessionListener sessionListener;
95 private Http1StreamListener streamListener;
96
97 private AsyncServerBootstrap() {
98 this.routeEntries = new ArrayList<>();
99 this.filters = new ArrayList<>();
100 }
101
102 public static AsyncServerBootstrap bootstrap() {
103 return new AsyncServerBootstrap();
104 }
105
106
107
108
109 public final AsyncServerBootstrap setCanonicalHostName(final String canonicalHostName) {
110 this.canonicalHostName = canonicalHostName;
111 return this;
112 }
113
114
115
116
117 public final AsyncServerBootstrap setIOReactorConfig(final IOReactorConfig ioReactorConfig) {
118 this.ioReactorConfig = ioReactorConfig;
119 return this;
120 }
121
122
123
124
125 public final AsyncServerBootstrap setHttp1Config(final Http1Config http1Config) {
126 this.http1Config = http1Config;
127 return this;
128 }
129
130
131
132
133 public final AsyncServerBootstrap setCharCodingConfig(final CharCodingConfig charCodingConfig) {
134 this.charCodingConfig = charCodingConfig;
135 return this;
136 }
137
138
139
140
141 public final AsyncServerBootstrap setHttpProcessor(final HttpProcessor httpProcessor) {
142 this.httpProcessor = httpProcessor;
143 return this;
144 }
145
146
147
148
149 public final AsyncServerBootstrap setConnectionReuseStrategy(final ConnectionReuseStrategy connStrategy) {
150 this.connStrategy = connStrategy;
151 return this;
152 }
153
154
155
156
157 public final AsyncServerBootstrap setTlsStrategy(final TlsStrategy tlsStrategy) {
158 this.tlsStrategy = tlsStrategy;
159 return this;
160 }
161
162
163
164
165 public final AsyncServerBootstrap setTlsHandshakeTimeout(final Timeout handshakeTimeout) {
166 this.handshakeTimeout = handshakeTimeout;
167 return this;
168 }
169
170
171
172
173 public final AsyncServerBootstrap setIOSessionDecorator(final Decorator<IOSession> ioSessionDecorator) {
174 this.ioSessionDecorator = ioSessionDecorator;
175 return this;
176 }
177
178
179
180
181 public final AsyncServerBootstrap setExceptionCallback(final Callback<Exception> exceptionCallback) {
182 this.exceptionCallback = exceptionCallback;
183 return this;
184 }
185
186
187
188
189 public final AsyncServerBootstrap setIOSessionListener(final IOSessionListener sessionListener) {
190 this.sessionListener = sessionListener;
191 return this;
192 }
193
194
195
196
197 @Deprecated
198 public final AsyncServerBootstrap setLookupRegistry(final org.apache.hc.core5.http.protocol.LookupRegistry<Supplier<AsyncServerExchangeHandler>> lookupRegistry) {
199 this.lookupRegistry = lookupRegistry;
200 return this;
201 }
202
203
204
205
206
207
208
209 public final AsyncServerBootstrap setRequestRouter(final HttpRequestMapper<Supplier<AsyncServerExchangeHandler>> requestRouter) {
210 this.requestRouter = requestRouter;
211 return this;
212 }
213
214
215
216
217
218
219 public final AsyncServerBootstrap setStreamListener(final Http1StreamListener streamListener) {
220 this.streamListener = streamListener;
221 return this;
222 }
223
224
225
226
227
228
229
230
231 public final AsyncServerBootstrap register(final String uriPattern, final Supplier<AsyncServerExchangeHandler> supplier) {
232 Args.notBlank(uriPattern, "URI pattern");
233 Args.notNull(supplier, "Exchange handler supplier");
234 routeEntries.add(new RequestRouter.Entry<>(uriPattern, supplier));
235 return this;
236 }
237
238
239
240
241
242
243
244
245
246
247
248 public final AsyncServerBootstrap register(final String hostname, final String uriPattern, final Supplier<AsyncServerExchangeHandler> supplier) {
249 Args.notBlank(hostname, "Hostname");
250 Args.notBlank(uriPattern, "URI pattern");
251 Args.notNull(supplier, "Exchange handler supplier");
252 routeEntries.add(new RequestRouter.Entry<>(hostname, uriPattern, supplier));
253 return this;
254 }
255
256
257
258
259 @Deprecated
260 public final AsyncServerBootstrap registerVirtual(final String hostname, final String uriPattern, final Supplier<AsyncServerExchangeHandler> supplier) {
261 return register(hostname, uriPattern, supplier);
262 }
263
264
265
266
267
268
269
270
271 public final <T> AsyncServerBootstrap register(
272 final String uriPattern,
273 final AsyncServerRequestHandler<T> requestHandler) {
274 register(uriPattern, () -> new BasicServerExchangeHandler<>(requestHandler));
275 return this;
276 }
277
278
279
280
281
282
283
284
285
286
287
288 public final <T> AsyncServerBootstrap register(final String hostname, final String uriPattern, final AsyncServerRequestHandler<T> requestHandler) {
289 register(hostname, uriPattern, () -> new BasicServerExchangeHandler<>(requestHandler));
290 return this;
291 }
292
293
294
295
296 @Deprecated
297 public final <T> AsyncServerBootstrap registerVirtual(
298 final String hostname,
299 final String uriPattern,
300 final AsyncServerRequestHandler<T> requestHandler) {
301 return register(hostname, uriPattern, requestHandler);
302 }
303
304
305
306
307 public final AsyncServerBootstrap addFilterBefore(final String existing, final String name, final AsyncFilterHandler filterHandler) {
308 Args.notBlank(existing, "Existing");
309 Args.notBlank(name, "Name");
310 Args.notNull(filterHandler, "Filter handler");
311 filters.add(new FilterEntry<>(FilterEntry.Position.BEFORE, name, filterHandler, existing));
312 return this;
313 }
314
315
316
317
318 public final AsyncServerBootstrap addFilterAfter(final String existing, final String name, final AsyncFilterHandler filterHandler) {
319 Args.notBlank(existing, "Existing");
320 Args.notBlank(name, "Name");
321 Args.notNull(filterHandler, "Filter handler");
322 filters.add(new FilterEntry<>(FilterEntry.Position.AFTER, name, filterHandler, existing));
323 return this;
324 }
325
326
327
328
329 public final AsyncServerBootstrap replaceFilter(final String existing, final AsyncFilterHandler filterHandler) {
330 Args.notBlank(existing, "Existing");
331 Args.notNull(filterHandler, "Filter handler");
332 filters.add(new FilterEntry<>(FilterEntry.Position.REPLACE, existing, filterHandler, existing));
333 return this;
334 }
335
336
337
338
339 public final AsyncServerBootstrap addFilterFirst(final String name, final AsyncFilterHandler filterHandler) {
340 Args.notNull(name, "Name");
341 Args.notNull(filterHandler, "Filter handler");
342 filters.add(new FilterEntry<>(FilterEntry.Position.FIRST, name, filterHandler, null));
343 return this;
344 }
345
346
347
348
349 public final AsyncServerBootstrap addFilterLast(final String name, final AsyncFilterHandler filterHandler) {
350 Args.notNull(name, "Name");
351 Args.notNull(filterHandler, "Filter handler");
352 filters.add(new FilterEntry<>(FilterEntry.Position.LAST, name, filterHandler, null));
353 return this;
354 }
355
356 public HttpAsyncServer create() {
357 final String actualCanonicalHostName = canonicalHostName != null ? canonicalHostName : InetAddressUtils.getCanonicalLocalHostName();
358 final HttpRequestMapper<Supplier<AsyncServerExchangeHandler>> requestRouterCopy;
359 if (lookupRegistry != null && requestRouter == null) {
360 final org.apache.hc.core5.http.protocol.RequestHandlerRegistry<Supplier<AsyncServerExchangeHandler>> handlerRegistry = new org.apache.hc.core5.http.protocol.RequestHandlerRegistry<>(
361 actualCanonicalHostName,
362 () -> lookupRegistry != null ? lookupRegistry : new org.apache.hc.core5.http.protocol.UriPatternMatcher<>());
363 for (final RequestRouter.Entry<Supplier<AsyncServerExchangeHandler>> entry: routeEntries) {
364 handlerRegistry.register(entry.uriAuthority != null ? entry.uriAuthority.getHostName() : null, entry.route.pattern, entry.route.handler);
365 }
366 requestRouterCopy = handlerRegistry;
367 } else {
368 if (routeEntries.isEmpty()) {
369 requestRouterCopy = requestRouter;
370 } else {
371 requestRouterCopy = RequestRouter.create(
372 new URIAuthority(actualCanonicalHostName),
373 UriPatternType.URI_PATTERN, routeEntries,
374 RequestRouter.IGNORE_PORT_AUTHORITY_RESOLVER,
375 requestRouter);
376 }
377 }
378 final HandlerFactory<AsyncServerExchangeHandler> handlerFactory;
379 if (!filters.isEmpty()) {
380 final NamedElementChain<AsyncFilterHandler> filterChainDefinition = new NamedElementChain<>();
381 filterChainDefinition.addLast(
382 new TerminalAsyncServerFilter(new DefaultAsyncResponseExchangeHandlerFactory(requestRouterCopy)),
383 StandardFilter.MAIN_HANDLER.name());
384 filterChainDefinition.addFirst(
385 new AsyncServerExpectationFilter(),
386 StandardFilter.EXPECT_CONTINUE.name());
387
388 for (final FilterEntry<AsyncFilterHandler> entry: filters) {
389 switch (entry.position) {
390 case AFTER:
391 filterChainDefinition.addAfter(entry.existing, entry.filterHandler, entry.name);
392 break;
393 case BEFORE:
394 filterChainDefinition.addBefore(entry.existing, entry.filterHandler, entry.name);
395 break;
396 case REPLACE:
397 filterChainDefinition.replace(entry.existing, entry.filterHandler);
398 break;
399 case FIRST:
400 filterChainDefinition.addFirst(entry.filterHandler, entry.name);
401 break;
402 case LAST:
403
404
405 filterChainDefinition.addBefore(StandardFilter.MAIN_HANDLER.name(), entry.filterHandler, entry.name);
406 break;
407 }
408 }
409
410 NamedElementChain<AsyncFilterHandler>.Node current = filterChainDefinition.getLast();
411 AsyncServerFilterChainElement execChain = null;
412 while (current != null) {
413 execChain = new AsyncServerFilterChainElement(current.getValue(), execChain);
414 current = current.getPrevious();
415 }
416
417 handlerFactory = new AsyncServerFilterChainExchangeHandlerFactory(execChain, exceptionCallback);
418 } else {
419 handlerFactory = new DefaultAsyncResponseExchangeHandlerFactory(requestRouterCopy, handler -> new BasicAsyncServerExpectationDecorator(handler, exceptionCallback));
420 }
421
422 final ServerHttp1StreamDuplexerFactory streamHandlerFactory = new ServerHttp1StreamDuplexerFactory(
423 httpProcessor != null ? httpProcessor : HttpProcessors.server(),
424 handlerFactory,
425 http1Config,
426 charCodingConfig != null ? charCodingConfig : CharCodingConfig.DEFAULT,
427 connStrategy != null ? connStrategy : DefaultConnectionReuseStrategy.INSTANCE,
428 new DefaultHttpRequestParserFactory(http1Config),
429 new DefaultHttpResponseWriterFactory(http1Config),
430 DefaultContentLengthStrategy.INSTANCE,
431 DefaultContentLengthStrategy.INSTANCE,
432 streamListener);
433 final IOEventHandlerFactory ioEventHandlerFactory = new ServerHttp1IOEventHandlerFactory(
434 streamHandlerFactory,
435 tlsStrategy,
436 handshakeTimeout);
437 return new HttpAsyncServer(ioEventHandlerFactory, ioReactorConfig, ioSessionDecorator, exceptionCallback,
438 sessionListener);
439 }
440
441 }