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.http.impl.execchain;
29
30 import java.io.IOException;
31 import java.net.URI;
32 import java.net.URISyntaxException;
33
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36 import org.apache.http.HttpException;
37 import org.apache.http.HttpHost;
38 import org.apache.http.HttpRequest;
39 import org.apache.http.ProtocolException;
40 import org.apache.http.annotation.Contract;
41 import org.apache.http.annotation.ThreadingBehavior;
42 import org.apache.http.auth.AuthScope;
43 import org.apache.http.auth.UsernamePasswordCredentials;
44 import org.apache.http.client.CredentialsProvider;
45 import org.apache.http.client.methods.CloseableHttpResponse;
46 import org.apache.http.client.methods.HttpExecutionAware;
47 import org.apache.http.client.methods.HttpRequestWrapper;
48 import org.apache.http.client.methods.HttpUriRequest;
49 import org.apache.http.client.params.ClientPNames;
50 import org.apache.http.client.protocol.HttpClientContext;
51 import org.apache.http.client.utils.URIUtils;
52 import org.apache.http.conn.routing.HttpRoute;
53 import org.apache.http.impl.client.BasicCredentialsProvider;
54 import org.apache.http.params.HttpParams;
55 import org.apache.http.protocol.HttpCoreContext;
56 import org.apache.http.protocol.HttpProcessor;
57 import org.apache.http.util.Args;
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73 @Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL)
74 @SuppressWarnings("deprecation")
75 public class ProtocolExec implements ClientExecChain {
76
77 private final Log log = LogFactory.getLog(getClass());
78
79 private final ClientExecChain requestExecutor;
80 private final HttpProcessor httpProcessor;
81
82 public ProtocolExec(final ClientExecChain requestExecutor, final HttpProcessor httpProcessor) {
83 Args.notNull(requestExecutor, "HTTP client request executor");
84 Args.notNull(httpProcessor, "HTTP protocol processor");
85 this.requestExecutor = requestExecutor;
86 this.httpProcessor = httpProcessor;
87 }
88
89 void rewriteRequestURI(
90 final HttpRequestWrapper request,
91 final HttpRoute route,
92 final boolean normalizeUri) throws ProtocolException {
93 final URI uri = request.getURI();
94 if (uri != null) {
95 try {
96 request.setURI(URIUtils.rewriteURIForRoute(uri, route, normalizeUri));
97 } catch (final URISyntaxException ex) {
98 throw new ProtocolException("Invalid URI: " + uri, ex);
99 }
100 }
101 }
102
103 @Override
104 public CloseableHttpResponse execute(
105 final HttpRoute route,
106 final HttpRequestWrapper request,
107 final HttpClientContext context,
108 final HttpExecutionAware execAware) throws IOException,
109 HttpException {
110 Args.notNull(route, "HTTP route");
111 Args.notNull(request, "HTTP request");
112 Args.notNull(context, "HTTP context");
113
114 final HttpRequest original = request.getOriginal();
115 URI uri = null;
116 if (original instanceof HttpUriRequest) {
117 uri = ((HttpUriRequest) original).getURI();
118 } else {
119 final String uriString = original.getRequestLine().getUri();
120 try {
121 uri = URI.create(uriString);
122 } catch (final IllegalArgumentException ex) {
123 if (this.log.isDebugEnabled()) {
124 this.log.debug("Unable to parse '" + uriString + "' as a valid URI; " +
125 "request URI and Host header may be inconsistent", ex);
126 }
127 }
128
129 }
130 request.setURI(uri);
131
132
133 rewriteRequestURI(request, route, context.getRequestConfig().isNormalizeUri());
134
135 final HttpParams params = request.getParams();
136 HttpHost virtualHost = (HttpHost) params.getParameter(ClientPNames.VIRTUAL_HOST);
137
138 if (virtualHost != null && virtualHost.getPort() == -1) {
139 final int port = route.getTargetHost().getPort();
140 if (port != -1) {
141 virtualHost = new HttpHost(virtualHost.getHostName(), port,
142 virtualHost.getSchemeName());
143 }
144 if (this.log.isDebugEnabled()) {
145 this.log.debug("Using virtual host" + virtualHost);
146 }
147 }
148
149 HttpHost target = null;
150 if (virtualHost != null) {
151 target = virtualHost;
152 } else {
153 if (uri != null && uri.isAbsolute() && uri.getHost() != null) {
154 target = new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme());
155 }
156 }
157 if (target == null) {
158 target = request.getTarget();
159 }
160 if (target == null) {
161 target = route.getTargetHost();
162 }
163
164
165 if (uri != null) {
166 final String userinfo = uri.getUserInfo();
167 if (userinfo != null) {
168 CredentialsProvider credsProvider = context.getCredentialsProvider();
169 if (credsProvider == null) {
170 credsProvider = new BasicCredentialsProvider();
171 context.setCredentialsProvider(credsProvider);
172 }
173 credsProvider.setCredentials(
174 new AuthScope(target),
175 new UsernamePasswordCredentials(userinfo));
176 }
177 }
178
179
180 context.setAttribute(HttpCoreContext.HTTP_TARGET_HOST, target);
181 context.setAttribute(HttpClientContext.HTTP_ROUTE, route);
182 context.setAttribute(HttpCoreContext.HTTP_REQUEST, request);
183
184 this.httpProcessor.process(request, context);
185
186 final CloseableHttpResponse response = this.requestExecutor.execute(route, request,
187 context, execAware);
188 try {
189
190 context.setAttribute(HttpCoreContext.HTTP_RESPONSE, response);
191 this.httpProcessor.process(response, context);
192 return response;
193 } catch (final RuntimeException ex) {
194 response.close();
195 throw ex;
196 } catch (final IOException ex) {
197 response.close();
198 throw ex;
199 } catch (final HttpException ex) {
200 response.close();
201 throw ex;
202 }
203 }
204
205 }