View Javadoc

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 The Apache MINA Project (dev@mina.apache.org)
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 }