View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.hc.client5.http.examples;
29  
30  import java.io.IOException;
31  import java.nio.ByteBuffer;
32  import java.nio.charset.StandardCharsets;
33  import java.util.concurrent.Future;
34  import java.util.concurrent.atomic.AtomicLong;
35  
36  import org.apache.hc.client5.http.async.AsyncExecCallback;
37  import org.apache.hc.client5.http.async.AsyncExecChain;
38  import org.apache.hc.client5.http.async.AsyncExecChainHandler;
39  import org.apache.hc.client5.http.async.methods.SimpleHttpRequest;
40  import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
41  import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder;
42  import org.apache.hc.client5.http.impl.ChainElement;
43  import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
44  import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
45  import org.apache.hc.core5.concurrent.FutureCallback;
46  import org.apache.hc.core5.http.ContentType;
47  import org.apache.hc.core5.http.EntityDetails;
48  import org.apache.hc.core5.http.Header;
49  import org.apache.hc.core5.http.HttpException;
50  import org.apache.hc.core5.http.HttpRequest;
51  import org.apache.hc.core5.http.HttpRequestInterceptor;
52  import org.apache.hc.core5.http.HttpResponse;
53  import org.apache.hc.core5.http.HttpStatus;
54  import org.apache.hc.core5.http.impl.BasicEntityDetails;
55  import org.apache.hc.core5.http.message.BasicHttpResponse;
56  import org.apache.hc.core5.http.message.StatusLine;
57  import org.apache.hc.core5.http.nio.AsyncDataConsumer;
58  import org.apache.hc.core5.http.nio.AsyncEntityProducer;
59  import org.apache.hc.core5.http.protocol.HttpContext;
60  import org.apache.hc.core5.io.CloseMode;
61  import org.apache.hc.core5.reactor.IOReactorConfig;
62  import org.apache.hc.core5.util.Timeout;
63  
64  /**
65   * This example demonstrates how to insert custom request interceptor and an execution interceptor
66   * to the request execution chain.
67   */
68  public class AsyncClientInterceptors {
69  
70      public static void main(final String[] args) throws Exception {
71  
72          final IOReactorConfig ioReactorConfig = IOReactorConfig.custom()
73                  .setSoTimeout(Timeout.ofSeconds(5))
74                  .build();
75  
76          final CloseableHttpAsyncClient client = HttpAsyncClients.custom()
77                  .setIOReactorConfig(ioReactorConfig)
78  
79                  // Add a simple request ID to each outgoing request
80  
81                  .addRequestInterceptorFirst(new HttpRequestInterceptor() {
82  
83                      private final AtomicLong count = new AtomicLong(0);
84  
85                      @Override
86                      public void process(
87                              final HttpRequest request,
88                              final EntityDetails entity,
89                              final HttpContext context) throws HttpException, IOException {
90                          request.setHeader("request-id", Long.toString(count.incrementAndGet()));
91                      }
92                  })
93  
94                  // Simulate a 404 response for some requests without passing the message down to the backend
95  
96                  .addExecInterceptorAfter(ChainElement.PROTOCOL.name(), "custom", new AsyncExecChainHandler() {
97  
98                      @Override
99                      public void execute(
100                             final HttpRequest request,
101                             final AsyncEntityProducer requestEntityProducer,
102                             final AsyncExecChain.Scope scope,
103                             final AsyncExecChain chain,
104                             final AsyncExecCallback asyncExecCallback) throws HttpException, IOException {
105                         final Header idHeader = request.getFirstHeader("request-id");
106                         if (idHeader != null && "13".equalsIgnoreCase(idHeader.getValue())) {
107                             final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_NOT_FOUND, "Oppsie");
108                             final ByteBuffer content = ByteBuffer.wrap("bad luck".getBytes(StandardCharsets.US_ASCII));
109                             final AsyncDataConsumer asyncDataConsumer = asyncExecCallback.handleResponse(
110                                     response,
111                                     new BasicEntityDetails(content.remaining(), ContentType.TEXT_PLAIN));
112                             asyncDataConsumer.consume(content);
113                             asyncDataConsumer.streamEnd(null);
114                         } else {
115                             chain.proceed(request, requestEntityProducer, scope, asyncExecCallback);
116                         }
117                     }
118 
119                 })
120 
121                 .build();
122 
123         client.start();
124 
125         final String requestUri = "http://httpbin.org/get";
126         for (int i = 0; i < 20; i++) {
127             final SimpleHttpRequest request = SimpleRequestBuilder.get(requestUri).build();
128             System.out.println("Executing request " + request);
129             final Future<SimpleHttpResponse> future = client.execute(
130                     request,
131                     new FutureCallback<SimpleHttpResponse>() {
132 
133                         @Override
134                         public void completed(final SimpleHttpResponse response) {
135                             System.out.println(request + "->" + new StatusLine(response));
136                             System.out.println(response.getBody());
137                         }
138 
139                         @Override
140                         public void failed(final Exception ex) {
141                             System.out.println(request + "->" + ex);
142                         }
143 
144                         @Override
145                         public void cancelled() {
146                             System.out.println(request + " cancelled");
147                         }
148 
149                     });
150             future.get();
151         }
152 
153         System.out.println("Shutting down");
154         client.close(CloseMode.GRACEFUL);
155     }
156 
157 }
158