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