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