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