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