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
28 package org.apache.hc.core5.testing.nio;
29
30 import java.io.IOException;
31 import java.net.InetSocketAddress;
32 import java.util.concurrent.Future;
33
34 import org.apache.hc.core5.function.Supplier;
35 import org.apache.hc.core5.http.ContentType;
36 import org.apache.hc.core5.http.EntityDetails;
37 import org.apache.hc.core5.http.Header;
38 import org.apache.hc.core5.http.HttpException;
39 import org.apache.hc.core5.http.HttpHost;
40 import org.apache.hc.core5.http.HttpRequest;
41 import org.apache.hc.core5.http.HttpResponse;
42 import org.apache.hc.core5.http.HttpStatus;
43 import org.apache.hc.core5.http.Message;
44 import org.apache.hc.core5.http.Method;
45 import org.apache.hc.core5.http.impl.bootstrap.AsyncRequesterBootstrap;
46 import org.apache.hc.core5.http.impl.bootstrap.AsyncServerBootstrap;
47 import org.apache.hc.core5.http.impl.bootstrap.HttpAsyncRequester;
48 import org.apache.hc.core5.http.impl.bootstrap.HttpAsyncServer;
49 import org.apache.hc.core5.http.nio.AsyncDataConsumer;
50 import org.apache.hc.core5.http.nio.AsyncEntityProducer;
51 import org.apache.hc.core5.http.nio.AsyncFilterChain;
52 import org.apache.hc.core5.http.nio.AsyncFilterHandler;
53 import org.apache.hc.core5.http.nio.AsyncPushProducer;
54 import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
55 import org.apache.hc.core5.http.nio.entity.StringAsyncEntityConsumer;
56 import org.apache.hc.core5.http.nio.entity.StringAsyncEntityProducer;
57 import org.apache.hc.core5.http.nio.ssl.BasicClientTlsStrategy;
58 import org.apache.hc.core5.http.nio.support.BasicRequestProducer;
59 import org.apache.hc.core5.http.nio.support.BasicResponseConsumer;
60 import org.apache.hc.core5.http.protocol.HttpContext;
61 import org.apache.hc.core5.http.protocol.UriPatternMatcher;
62 import org.apache.hc.core5.io.CloseMode;
63 import org.apache.hc.core5.reactor.IOReactorConfig;
64 import org.apache.hc.core5.reactor.ListenerEndpoint;
65 import org.apache.hc.core5.testing.SSLTestContexts;
66 import org.apache.hc.core5.testing.classic.LoggingConnPoolListener;
67 import org.apache.hc.core5.util.Timeout;
68 import org.hamcrest.CoreMatchers;
69 import org.hamcrest.MatcherAssert;
70 import org.junit.Rule;
71 import org.junit.Test;
72 import org.junit.rules.ExternalResource;
73 import org.slf4j.Logger;
74 import org.slf4j.LoggerFactory;
75
76 public class AsyncServerBootstrapFilterTest {
77
78 private final Logger log = LoggerFactory.getLogger(getClass());
79
80 private static final Timeout TIMEOUT = Timeout.ofSeconds(30);
81
82 private HttpAsyncServer server;
83
84 @Rule
85 public ExternalResource serverResource = new ExternalResource() {
86
87 @Override
88 protected void before() throws Throwable {
89 log.debug("Starting up test server");
90 server = AsyncServerBootstrap.bootstrap()
91 .setLookupRegistry(new UriPatternMatcher<Supplier<AsyncServerExchangeHandler>>())
92 .setIOReactorConfig(
93 IOReactorConfig.custom()
94 .setSoTimeout(TIMEOUT)
95 .build())
96 .register("*", new Supplier<AsyncServerExchangeHandler>() {
97
98 @Override
99 public AsyncServerExchangeHandler get() {
100 return new EchoHandler(2048);
101 }
102
103 })
104 .addFilterLast("test-filter", new AsyncFilterHandler() {
105
106 @Override
107 public AsyncDataConsumer handle(
108 final HttpRequest request,
109 final EntityDetails entityDetails,
110 final HttpContext context,
111 final AsyncFilterChain.ResponseTrigger responseTrigger,
112 final AsyncFilterChain chain) throws HttpException, IOException {
113 return chain.proceed(request, entityDetails, context, new AsyncFilterChain.ResponseTrigger() {
114
115 @Override
116 public void sendInformation(
117 final HttpResponse response) throws HttpException, IOException {
118 responseTrigger.sendInformation(response);
119 }
120
121 @Override
122 public void submitResponse(
123 final HttpResponse response,
124 final AsyncEntityProducer entityProducer) throws HttpException, IOException {
125 response.setHeader("X-Test-Filter", "active");
126 responseTrigger.submitResponse(response, entityProducer);
127 }
128
129 @Override
130 public void pushPromise(
131 final HttpRequest promise,
132 final AsyncPushProducer responseProducer) throws HttpException, IOException {
133 responseTrigger.pushPromise(promise, responseProducer);
134 }
135
136 });
137 }
138 })
139 .setStreamListener(LoggingHttp1StreamListener.INSTANCE_SERVER)
140 .setIOSessionDecorator(LoggingIOSessionDecorator.INSTANCE)
141 .setExceptionCallback(LoggingExceptionCallback.INSTANCE)
142 .setIOSessionListener(LoggingIOSessionListener.INSTANCE)
143 .create();
144 }
145
146 @Override
147 protected void after() {
148 log.debug("Shutting down test server");
149 if (server != null) {
150 server.close(CloseMode.GRACEFUL);
151 }
152 }
153
154 };
155
156 private HttpAsyncRequester requester;
157
158 @Rule
159 public ExternalResource clientResource = new ExternalResource() {
160
161 @Override
162 protected void before() throws Throwable {
163 log.debug("Starting up test client");
164 requester = AsyncRequesterBootstrap.bootstrap()
165 .setIOReactorConfig(IOReactorConfig.custom()
166 .setSoTimeout(TIMEOUT)
167 .build())
168 .setTlsStrategy(new BasicClientTlsStrategy(SSLTestContexts.createClientSSLContext()))
169 .setStreamListener(LoggingHttp1StreamListener.INSTANCE_CLIENT)
170 .setConnPoolListener(LoggingConnPoolListener.INSTANCE)
171 .setIOSessionDecorator(LoggingIOSessionDecorator.INSTANCE)
172 .setExceptionCallback(LoggingExceptionCallback.INSTANCE)
173 .setIOSessionListener(LoggingIOSessionListener.INSTANCE)
174 .create();
175 }
176
177 @Override
178 protected void after() {
179 log.debug("Shutting down test client");
180 if (requester != null) {
181 requester.close(CloseMode.GRACEFUL);
182 }
183 }
184
185 };
186
187 @Test
188 public void testFilters() throws Exception {
189 server.start();
190 final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0));
191 final ListenerEndpoint listener = future.get();
192 final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
193 requester.start();
194
195 final HttpHost target = new HttpHost("http", "localhost", address.getPort());
196 final Future<Message<HttpResponse, String>> resultFuture = requester.execute(
197 new BasicRequestProducer(Method.POST, target, "/filters",
198 new StringAsyncEntityProducer("some stuff", ContentType.TEXT_PLAIN)),
199 new BasicResponseConsumer<>(new StringAsyncEntityConsumer()), TIMEOUT, null);
200 final Message<HttpResponse, String> message = resultFuture.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
201 MatcherAssert.assertThat(message, CoreMatchers.notNullValue());
202 final HttpResponse response = message.getHead();
203 MatcherAssert.assertThat(response.getCode(), CoreMatchers.equalTo(HttpStatus.SC_OK));
204 final Header testFilterHeader = response.getHeader("X-Test-Filter");
205 MatcherAssert.assertThat(testFilterHeader, CoreMatchers.notNullValue());
206 }
207
208 }