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