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 .setExceptionCallback(e -> e.printStackTrace())
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", (request, entityDetails, context, responseTrigger, chain) -> {
115 if (request.getRequestUri().equals("/back-door")) {
116 responseTrigger.submitResponse(
117 new BasicHttpResponse(HttpStatus.SC_OK),
118 AsyncEntityProducers.create("Welcome"));
119 return null;
120 }
121 return chain.proceed(request, entityDetails, context, new AsyncFilterChain.ResponseTrigger() {
122
123 @Override
124 public void sendInformation(
125 final HttpResponse response) throws HttpException, IOException {
126 responseTrigger.sendInformation(response);
127 }
128
129 @Override
130 public void submitResponse(
131 final HttpResponse response, final AsyncEntityProducer entityProducer) throws HttpException, IOException {
132 response.addHeader("X-Filter", "My-Filter");
133 responseTrigger.submitResponse(response, entityProducer);
134 }
135
136 @Override
137 public void pushPromise(
138 final HttpRequest promise, final AsyncPushProducer responseProducer) throws HttpException, IOException {
139 responseTrigger.pushPromise(promise, responseProducer);
140 }
141
142 });
143 })
144
145
146
147 .register("*", new AsyncServerRequestHandler<Message<HttpRequest, String>>() {
148
149 @Override
150 public AsyncRequestConsumer<Message<HttpRequest, String>> prepare(
151 final HttpRequest request,
152 final EntityDetails entityDetails,
153 final HttpContext context) throws HttpException {
154 return new BasicRequestConsumer<>(entityDetails != null ? new StringAsyncEntityConsumer() : null);
155 }
156
157 @Override
158 public void handle(
159 final Message<HttpRequest, String> requestMessage,
160 final ResponseTrigger responseTrigger,
161 final HttpContext context) throws HttpException, IOException {
162
163 responseTrigger.submitResponse(
164 AsyncResponseBuilder.create(HttpStatus.SC_OK)
165 .setEntity("Hello")
166 .build(),
167 context);
168 }
169 })
170 .create();
171
172 Runtime.getRuntime().addShutdownHook(new Thread(() -> {
173 System.out.println("HTTP server shutting down");
174 server.close(CloseMode.GRACEFUL);
175 }));
176
177 server.start();
178 final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(port), URIScheme.HTTP);
179 final ListenerEndpoint listenerEndpoint = future.get();
180 System.out.print("Listening on " + listenerEndpoint.getAddress());
181 server.awaitShutdown(TimeValue.MAX_VALUE);
182 }
183
184 }