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