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.client5.http.examples;
29
30 import java.nio.ByteBuffer;
31 import java.nio.charset.StandardCharsets;
32 import java.util.concurrent.Future;
33 import java.util.concurrent.atomic.AtomicLong;
34
35 import org.apache.hc.client5.http.async.methods.SimpleHttpRequest;
36 import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
37 import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder;
38 import org.apache.hc.client5.http.impl.ChainElement;
39 import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
40 import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
41 import org.apache.hc.core5.concurrent.FutureCallback;
42 import org.apache.hc.core5.http.ContentType;
43 import org.apache.hc.core5.http.EntityDetails;
44 import org.apache.hc.core5.http.Header;
45 import org.apache.hc.core5.http.HttpRequest;
46 import org.apache.hc.core5.http.HttpRequestInterceptor;
47 import org.apache.hc.core5.http.HttpResponse;
48 import org.apache.hc.core5.http.HttpStatus;
49 import org.apache.hc.core5.http.impl.BasicEntityDetails;
50 import org.apache.hc.core5.http.message.BasicHttpResponse;
51 import org.apache.hc.core5.http.message.StatusLine;
52 import org.apache.hc.core5.http.nio.AsyncDataConsumer;
53 import org.apache.hc.core5.http.protocol.HttpContext;
54 import org.apache.hc.core5.io.CloseMode;
55 import org.apache.hc.core5.reactor.IOReactorConfig;
56 import org.apache.hc.core5.util.Timeout;
57
58
59
60
61
62 public class AsyncClientInterceptors {
63
64 public static void main(final String[] args) throws Exception {
65
66 final IOReactorConfig ioReactorConfig = IOReactorConfig.custom()
67 .setSoTimeout(Timeout.ofSeconds(5))
68 .build();
69
70 final CloseableHttpAsyncClient client = HttpAsyncClients.custom()
71 .setIOReactorConfig(ioReactorConfig)
72
73
74
75 .addRequestInterceptorFirst(new HttpRequestInterceptor() {
76
77 private final AtomicLong count = new AtomicLong(0);
78
79 @Override
80 public void process(
81 final HttpRequest request,
82 final EntityDetails entity,
83 final HttpContext context) {
84 request.setHeader("request-id", Long.toString(count.incrementAndGet()));
85 }
86 })
87
88
89
90 .addExecInterceptorAfter(ChainElement.PROTOCOL.name(), "custom", (request, requestEntityProducer, scope, chain, asyncExecCallback) -> {
91 final Header idHeader = request.getFirstHeader("request-id");
92 if (idHeader != null && "13".equalsIgnoreCase(idHeader.getValue())) {
93 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_NOT_FOUND, "Oppsie");
94 final ByteBuffer content = ByteBuffer.wrap("bad luck".getBytes(StandardCharsets.US_ASCII));
95 final AsyncDataConsumer asyncDataConsumer = asyncExecCallback.handleResponse(
96 response,
97 new BasicEntityDetails(content.remaining(), ContentType.TEXT_PLAIN));
98 asyncDataConsumer.consume(content);
99 asyncDataConsumer.streamEnd(null);
100 } else {
101 chain.proceed(request, requestEntityProducer, scope, asyncExecCallback);
102 }
103 })
104
105 .build();
106
107 client.start();
108
109 final String requestUri = "http://httpbin.org/get";
110 for (int i = 0; i < 20; i++) {
111 final SimpleHttpRequest request = SimpleRequestBuilder.get(requestUri).build();
112 System.out.println("Executing request " + request);
113 final Future<SimpleHttpResponse> future = client.execute(
114 request,
115 new FutureCallback<SimpleHttpResponse>() {
116
117 @Override
118 public void completed(final SimpleHttpResponse response) {
119 System.out.println(request + "->" + new StatusLine(response));
120 System.out.println(response.getBody());
121 }
122
123 @Override
124 public void failed(final Exception ex) {
125 System.out.println(request + "->" + ex);
126 }
127
128 @Override
129 public void cancelled() {
130 System.out.println(request + " cancelled");
131 }
132
133 });
134 future.get();
135 }
136
137 System.out.println("Shutting down");
138 client.close(CloseMode.GRACEFUL);
139 }
140
141 }
142