1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 *
19 */
20 package org.apache.mina.proxy.handlers.http;
21
22 import java.net.InetSocketAddress;
23 import java.net.MalformedURLException;
24 import java.net.URL;
25 import java.util.List;
26 import java.util.Map;
27
28 import org.apache.mina.proxy.ProxyAuthException;
29 import org.apache.mina.proxy.handlers.ProxyRequest;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 /**
34 * HttpProxyRequest.java - Wrapper class for HTTP requests.
35 *
36 * @author <a href="http://mina.apache.org">Apache MINA Project</a>
37 * @since MINA 2.0.0-M3
38 */
39 public class HttpProxyRequest extends ProxyRequest {
40 private final static Logger logger = LoggerFactory
41 .getLogger(HttpProxyRequest.class);
42
43 /**
44 * The HTTP verb.
45 */
46 public final String httpVerb;
47
48 /**
49 * The HTTP URI.
50 */
51 public final String httpURI;
52
53 /**
54 * The HTTP protocol version.
55 */
56 private String httpVersion;
57
58 /**
59 * The target hostname.
60 */
61 private String host;
62
63 /**
64 * The request headers.
65 */
66 private Map<String, List<String>> headers;
67
68 /**
69 * The additionnal properties supplied to use with the proxy for
70 * authentication for example.
71 */
72 private transient Map<String, String> properties;
73
74 /**
75 * Constructor which creates a HTTP/1.0 CONNECT request to the specified
76 * endpoint.
77 *
78 * @param endpointAddress the endpoint to connect to
79 */
80 public HttpProxyRequest(final InetSocketAddress endpointAddress) {
81 this(endpointAddress, HttpProxyConstants.HTTP_1_0, null);
82 }
83
84 /**
85 * Constructor which creates a CONNECT request to the specified endpoint
86 * using the provided protocol version.
87 *
88 * @param endpointAddress the endpoint to connect to
89 * @param httpVersion the HTTP protocol version
90 */
91 public HttpProxyRequest(final InetSocketAddress endpointAddress,
92 final String httpVersion) {
93 this(endpointAddress, httpVersion, null);
94 }
95
96 /**
97 * Constructor which creates a CONNECT request to the specified endpoint
98 * using the provided protocol version and setting the requested headers.
99 *
100 * @param endpointAddress the endpoint to connect to
101 * @param httpVersion the HTTP protocol version
102 * @param headers the additionnal http headers
103 */
104 public HttpProxyRequest(final InetSocketAddress endpointAddress,
105 final String httpVersion, final Map<String, List<String>> headers) {
106 this.httpVerb = HttpProxyConstants.CONNECT;
107 if (!endpointAddress.isUnresolved()) {
108 this.httpURI = endpointAddress.getHostName() + ":"
109 + endpointAddress.getPort();
110 } else {
111 this.httpURI = endpointAddress.getAddress().getHostAddress() + ":"
112 + endpointAddress.getPort();
113 }
114
115 this.httpVersion = httpVersion;
116 this.headers = headers;
117 }
118
119 /**
120 * Constructor which creates a HTTP/1.0 GET request to the specified
121 * http URI.
122 *
123 * @param httpURI the target URI
124 */
125 public HttpProxyRequest(final String httpURI) {
126 this(HttpProxyConstants.GET, httpURI, HttpProxyConstants.HTTP_1_0, null);
127 }
128
129 /**
130 * Constructor which creates a GET request to the specified http URI
131 * using the provided protocol version
132 *
133 * @param httpURI the target URI
134 * @param httpVersion the HTTP protocol version
135 */
136 public HttpProxyRequest(final String httpURI, final String httpVersion) {
137 this(HttpProxyConstants.GET, httpURI, httpVersion, null);
138 }
139
140 /**
141 * Constructor which creates a request using the provided HTTP verb targeted at
142 * the specified http URI using the provided protocol version.
143 *
144 * @param httpVerb the HTTP verb to use
145 * @param httpURI the target URI
146 * @param httpVersion the HTTP protocol version
147 */
148 public HttpProxyRequest(final String httpVerb, final String httpURI,
149 final String httpVersion) {
150 this(httpVerb, httpURI, httpVersion, null);
151 }
152
153 /**
154 * Constructor which creates a request using the provided HTTP verb targeted at
155 * the specified http URI using the provided protocol version and setting the
156 * requested headers.
157 *
158 * @param httpVerb the HTTP verb to use
159 * @param httpURI the target URI
160 * @param httpVersion the HTTP protocol version
161 * @param headers the additional http headers
162 */
163 public HttpProxyRequest(final String httpVerb, final String httpURI,
164 final String httpVersion, final Map<String, List<String>> headers) {
165 this.httpVerb = httpVerb;
166 this.httpURI = httpURI;
167 this.httpVersion = httpVersion;
168 this.headers = headers;
169 }
170
171 /**
172 * Returns the HTTP request verb.
173 */
174 public final String getHttpVerb() {
175 return httpVerb;
176 }
177
178 /**
179 * Returns the HTTP version.
180 */
181 public String getHttpVersion() {
182 return httpVersion;
183 }
184
185 /**
186 * Sets the HTTP version.
187 *
188 * @param httpVersion the HTTP protocol version
189 */
190 public void setHttpVersion(String httpVersion) {
191 this.httpVersion = httpVersion;
192 }
193
194 /**
195 * Returns the host to which we are connecting.
196 */
197 public synchronized final String getHost() {
198 if (host == null) {
199 if (getEndpointAddress() != null &&
200 !getEndpointAddress().isUnresolved()) {
201 host = getEndpointAddress().getHostName();
202 }
203
204 if (host == null && httpURI != null) {
205 try {
206 host = (new URL(httpURI)).getHost();
207 } catch (MalformedURLException e) {
208 logger.debug("Malformed URL", e);
209 }
210 }
211 }
212
213 return host;
214 }
215
216 /**
217 * Returns the request HTTP URI.
218 */
219 public final String getHttpURI() {
220 return httpURI;
221 }
222
223 /**
224 * Returns the HTTP headers.
225 */
226 public final Map<String, List<String>> getHeaders() {
227 return headers;
228 }
229
230 /**
231 * Set the HTTP headers.
232 */
233 public final void setHeaders(Map<String, List<String>> headers) {
234 this.headers = headers;
235 }
236
237 /**
238 * Returns additional properties for the request.
239 */
240 public Map<String, String> getProperties() {
241 return properties;
242 }
243
244 /**
245 * Set additional properties for the request.
246 */
247 public void setProperties(Map<String, String> properties) {
248 this.properties = properties;
249 }
250
251 /**
252 * Check if the given property(ies) is(are) set. Otherwise throws a
253 * {@link ProxyAuthException}.
254 */
255 public void checkRequiredProperties(String... propNames) throws ProxyAuthException {
256 StringBuilder sb = new StringBuilder();
257 for (String propertyName : propNames) {
258 if (properties.get(propertyName) == null) {
259 sb.append(propertyName).append(' ');
260 }
261 }
262 if (sb.length() > 0) {
263 sb.append("property(ies) missing in request");
264 throw new ProxyAuthException(sb.toString());
265 }
266 }
267
268 /**
269 * Returns the string representation of the HTTP request .
270 */
271 public String toHttpString() {
272 StringBuilder sb = new StringBuilder();
273
274 sb.append(getHttpVerb()).append(' ').append(getHttpURI()).append(' ')
275 .append(getHttpVersion()).append(HttpProxyConstants.CRLF);
276
277 boolean hostHeaderFound = false;
278
279 if (getHeaders() != null) {
280 for (Map.Entry<String, List<String>> header : getHeaders()
281 .entrySet()) {
282 if (!hostHeaderFound) {
283 hostHeaderFound = header.getKey().equalsIgnoreCase("host");
284 }
285
286 for (String value : header.getValue()) {
287 sb.append(header.getKey()).append(": ").append(value)
288 .append(HttpProxyConstants.CRLF);
289 }
290 }
291
292 if (!hostHeaderFound
293 && getHttpVersion() == HttpProxyConstants.HTTP_1_1) {
294 sb.append("Host: ").append(getHost()).append(
295 HttpProxyConstants.CRLF);
296 }
297 }
298
299 sb.append(HttpProxyConstants.CRLF);
300
301 return sb.toString();
302 }
303 }