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.examples;
28
29 import java.io.IOException;
30 import java.net.InetSocketAddress;
31 import java.util.concurrent.Future;
32 import java.util.concurrent.TimeUnit;
33
34 import org.apache.hc.core5.http.EntityDetails;
35 import org.apache.hc.core5.http.HttpException;
36 import org.apache.hc.core5.http.HttpRequest;
37 import org.apache.hc.core5.http.HttpResponse;
38 import org.apache.hc.core5.http.HttpStatus;
39 import org.apache.hc.core5.http.Message;
40 import org.apache.hc.core5.http.URIScheme;
41 import org.apache.hc.core5.http.impl.bootstrap.AsyncServerBootstrap;
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.message.BasicHttpResponse;
45 import org.apache.hc.core5.http.nio.AsyncEntityProducer;
46 import org.apache.hc.core5.http.nio.AsyncFilterChain;
47 import org.apache.hc.core5.http.nio.AsyncPushProducer;
48 import org.apache.hc.core5.http.nio.AsyncRequestConsumer;
49 import org.apache.hc.core5.http.nio.AsyncServerRequestHandler;
50 import org.apache.hc.core5.http.nio.entity.AsyncEntityProducers;
51 import org.apache.hc.core5.http.nio.entity.StringAsyncEntityConsumer;
52 import org.apache.hc.core5.http.nio.support.AbstractAsyncServerAuthFilter;
53 import org.apache.hc.core5.http.nio.support.AsyncResponseBuilder;
54 import org.apache.hc.core5.http.nio.support.BasicRequestConsumer;
55 import org.apache.hc.core5.http.protocol.HttpContext;
56 import org.apache.hc.core5.io.CloseMode;
57 import org.apache.hc.core5.net.URIAuthority;
58 import org.apache.hc.core5.reactor.IOReactorConfig;
59 import org.apache.hc.core5.reactor.ListenerEndpoint;
60 import org.apache.hc.core5.util.TimeValue;
61
62
63
64
65 public class AsyncServerFilterExample {
66
67 public static void main(final String[] args) throws Exception {
68 int port = 8080;
69 if (args.length >= 1) {
70 port = Integer.parseInt(args[0]);
71 }
72
73 final IOReactorConfig config = IOReactorConfig.custom()
74 .setSoTimeout(15, TimeUnit.SECONDS)
75 .setTcpNoDelay(true)
76 .build();
77
78 final HttpAsyncServer server = AsyncServerBootstrap.bootstrap()
79 .setIOReactorConfig(config)
80
81
82
83 .replaceFilter(StandardFilter.EXPECT_CONTINUE.name(), new AbstractAsyncServerAuthFilter<String>(true) {
84
85 @Override
86 protected String parseChallengeResponse(
87 final String authorizationValue, final HttpContext context) throws HttpException {
88 return authorizationValue;
89 }
90
91 @Override
92 protected boolean authenticate(
93 final String challengeResponse,
94 final URIAuthority authority,
95 final String requestUri,
96 final HttpContext context) {
97 return "let me pass".equals(challengeResponse);
98 }
99
100 @Override
101 protected String generateChallenge(
102 final String challengeResponse,
103 final URIAuthority authority,
104 final String requestUri,
105 final HttpContext context) {
106 return "who goes there?";
107 }
108
109 })
110
111
112
113 .addFilterFirst("my-filter", (request, entityDetails, context, responseTrigger, chain) -> {
114 if (request.getRequestUri().equals("/back-door")) {
115 responseTrigger.submitResponse(
116 new BasicHttpResponse(HttpStatus.SC_OK),
117 AsyncEntityProducers.create("Welcome"));
118 return null;
119 }
120 return chain.proceed(request, entityDetails, context, new AsyncFilterChain.ResponseTrigger() {
121
122 @Override
123 public void sendInformation(
124 final HttpResponse response) throws HttpException, IOException {
125 responseTrigger.sendInformation(response);
126 }
127
128 @Override
129 public void submitResponse(
130 final HttpResponse response, final AsyncEntityProducer entityProducer) throws HttpException, IOException {
131 response.addHeader("X-Filter", "My-Filter");
132 responseTrigger.submitResponse(response, entityProducer);
133 }
134
135 @Override
136 public void pushPromise(
137 final HttpRequest promise, final AsyncPushProducer responseProducer) throws HttpException, IOException {
138 responseTrigger.pushPromise(promise, responseProducer);
139 }
140
141 });
142 })
143
144
145
146 .register("*", new AsyncServerRequestHandler<Message<HttpRequest, String>>() {
147
148 @Override
149 public AsyncRequestConsumer<Message<HttpRequest, String>> prepare(
150 final HttpRequest request,
151 final EntityDetails entityDetails,
152 final HttpContext context) throws HttpException {
153 return new BasicRequestConsumer<>(entityDetails != null ? new StringAsyncEntityConsumer() : null);
154 }
155
156 @Override
157 public void handle(
158 final Message<HttpRequest, String> requestMessage,
159 final ResponseTrigger responseTrigger,
160 final HttpContext context) throws HttpException, IOException {
161
162 responseTrigger.submitResponse(
163 AsyncResponseBuilder.create(HttpStatus.SC_OK)
164 .setEntity("Hello")
165 .build(),
166 context);
167 }
168 })
169 .create();
170
171 Runtime.getRuntime().addShutdownHook(new Thread(() -> {
172 System.out.println("HTTP server shutting down");
173 server.close(CloseMode.GRACEFUL);
174 }));
175
176 server.start();
177 final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(port), URIScheme.HTTP);
178 final ListenerEndpoint listenerEndpoint = future.get();
179 System.out.print("Listening on " + listenerEndpoint.getAddress());
180 server.awaitShutdown(TimeValue.MAX_VALUE);
181 }
182
183 }