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.testing.async;
29
30 import java.io.IOException;
31 import java.net.URI;
32 import java.net.URISyntaxException;
33 import java.nio.ByteBuffer;
34 import java.util.List;
35 import java.util.concurrent.atomic.AtomicBoolean;
36
37 import org.apache.hc.client5.testing.redirect.Redirect;
38 import org.apache.hc.client5.testing.redirect.RedirectResolver;
39 import org.apache.hc.core5.http.EntityDetails;
40 import org.apache.hc.core5.http.Header;
41 import org.apache.hc.core5.http.HeaderElements;
42 import org.apache.hc.core5.http.HttpException;
43 import org.apache.hc.core5.http.HttpHeaders;
44 import org.apache.hc.core5.http.HttpRequest;
45 import org.apache.hc.core5.http.HttpResponse;
46 import org.apache.hc.core5.http.ProtocolException;
47 import org.apache.hc.core5.http.message.BasicHeader;
48 import org.apache.hc.core5.http.message.BasicHttpResponse;
49 import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
50 import org.apache.hc.core5.http.nio.CapacityChannel;
51 import org.apache.hc.core5.http.nio.DataStreamChannel;
52 import org.apache.hc.core5.http.nio.ResponseChannel;
53 import org.apache.hc.core5.http.protocol.HttpContext;
54 import org.apache.hc.core5.util.Args;
55
56 public class RedirectingAsyncDecorator implements AsyncServerExchangeHandler {
57
58 private final AsyncServerExchangeHandler exchangeHandler;
59 private final RedirectResolver redirectResolver;
60 private final AtomicBoolean redirecting;
61
62 public RedirectingAsyncDecorator(final AsyncServerExchangeHandler exchangeHandler,
63 final RedirectResolver redirectResolver) {
64 this.exchangeHandler = Args.notNull(exchangeHandler, "Exchange handler");
65 this.redirectResolver = redirectResolver;
66 this.redirecting = new AtomicBoolean();
67 }
68
69 private Redirect resolveRedirect(final HttpRequest request) throws HttpException {
70 try {
71 final URI requestURI = request.getUri();
72 return redirectResolver != null ? redirectResolver.resolve(requestURI) : null;
73 } catch (final URISyntaxException ex) {
74 throw new ProtocolException(ex.getMessage(), ex);
75 }
76 }
77
78 private HttpResponse createRedirectResponse(final Redirect redirect) {
79 final HttpResponse response = new BasicHttpResponse(redirect.status);
80 if (redirect.location != null) {
81 response.addHeader(new BasicHeader(HttpHeaders.LOCATION, redirect.location));
82 }
83 switch (redirect.connControl) {
84 case KEEP_ALIVE:
85 response.addHeader(new BasicHeader(HttpHeaders.CONNECTION, HeaderElements.KEEP_ALIVE));
86 break;
87 case CLOSE:
88 response.addHeader(new BasicHeader(HttpHeaders.CONNECTION, HeaderElements.CLOSE));
89 }
90 return response;
91 }
92
93 @Override
94 public void handleRequest(final HttpRequest request,
95 final EntityDetails entityDetails,
96 final ResponseChannel responseChannel,
97 final HttpContext context) throws HttpException, IOException {
98 final Redirect redirect = resolveRedirect(request);
99 if (redirect != null) {
100 responseChannel.sendResponse(createRedirectResponse(redirect), null, context);
101 redirecting.set(true);
102 } else {
103 exchangeHandler.handleRequest(request, entityDetails, responseChannel, context);
104 }
105 }
106
107 @Override
108 public final void updateCapacity(final CapacityChannel capacityChannel) throws IOException {
109 if (!redirecting.get()) {
110 exchangeHandler.updateCapacity(capacityChannel);
111 } else {
112 capacityChannel.update(Integer.MAX_VALUE);
113 }
114 }
115
116 @Override
117 public final void consume(final ByteBuffer src) throws IOException {
118 if (!redirecting.get()) {
119 exchangeHandler.consume(src);
120 }
121 }
122
123 @Override
124 public final void streamEnd(final List<? extends Header> trailers) throws HttpException, IOException {
125 if (!redirecting.get()) {
126 exchangeHandler.streamEnd(trailers);
127 }
128 }
129
130 @Override
131 public int available() {
132 if (!redirecting.get()) {
133 return exchangeHandler.available();
134 } else {
135 return 0;
136 }
137 }
138
139 @Override
140 public void produce(final DataStreamChannel channel) throws IOException {
141 if (!redirecting.get()) {
142 exchangeHandler.produce(channel);
143 }
144 }
145
146 @Override
147 public void failed(final Exception cause) {
148 if (!redirecting.get()) {
149 exchangeHandler.failed(cause);
150 }
151 }
152
153 @Override
154 public void releaseResources() {
155 exchangeHandler.releaseResources();
156 }
157
158 }