View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.hc.core5.http.message;
29  
30  import org.apache.hc.core5.http.HttpHost;
31  import org.apache.hc.core5.http.HttpRequest;
32  import org.apache.hc.core5.http.Method;
33  import org.apache.hc.core5.http.ProtocolVersion;
34  import org.apache.hc.core5.http.URIScheme;
35  import org.apache.hc.core5.net.URIAuthority;
36  import org.apache.hc.core5.util.Args;
37  import org.apache.hc.core5.util.TextUtils;
38  
39  import java.net.URI;
40  import java.net.URISyntaxException;
41  
42  /**
43   * Basic implementation of {@link HttpRequest}.
44   *
45   * @since 4.0
46   */
47  public class BasicHttpRequest extends HeaderGroup implements HttpRequest {
48  
49      private static final long serialVersionUID = 1L;
50  
51      private final String method;
52      private String path;
53      private String scheme;
54      private URIAuthority authority;
55      private ProtocolVersion version;
56      private URI requestUri;
57      private boolean absoluteRequestUri;
58  
59      /**
60       * Creates request message with the given method, host and request path.
61       *
62       * @param method request method.
63       * @param scheme request scheme.
64       * @param authority request authority.
65       * @param path request path.
66       *
67       * @since 5.1
68       */
69      public BasicHttpRequest(final String method, final String scheme, final URIAuthority authority, final String path) {
70          super();
71          this.method = Args.notNull(method, "Method name");
72          this.scheme = scheme;
73          this.authority = authority;
74          this.path = path;
75      }
76  
77      /**
78       * Creates request message with the given method and request path.
79       *
80       * @param method request method.
81       * @param path request path.
82       */
83      public BasicHttpRequest(final String method, final String path) {
84          super();
85          this.method = method;
86          if (path != null) {
87              try {
88                  setUri(new URI(path));
89              } catch (final URISyntaxException ex) {
90                  this.path = path;
91              }
92          }
93      }
94  
95      /**
96       * Creates request message with the given method, host and request path.
97       *
98       * @param method request method.
99       * @param host request host.
100      * @param path request path.
101      *
102      * @since 5.0
103      */
104     public BasicHttpRequest(final String method, final HttpHost host, final String path) {
105         super();
106         this.method = Args.notNull(method, "Method name");
107         this.scheme = host != null ? host.getSchemeName() : null;
108         this.authority = host != null ? new URIAuthority(host) : null;
109         this.path = path;
110     }
111 
112     /**
113      * Creates request message with the given method, request URI.
114      *
115      * @param method request method.
116      * @param requestUri request URI.
117      *
118      * @since 5.0
119      */
120     public BasicHttpRequest(final String method, final URI requestUri) {
121         super();
122         this.method = Args.notNull(method, "Method name");
123         setUri(Args.notNull(requestUri, "Request URI"));
124     }
125 
126     /**
127      * Creates request message with the given method and request path.
128      *
129      * @param method request method.
130      * @param path request path.
131      *
132      * @since 5.0
133      */
134     public BasicHttpRequest(final Method method, final String path) {
135         super();
136         this.method = Args.notNull(method, "Method").name();
137         if (path != null) {
138             try {
139                 setUri(new URI(path));
140             } catch (final URISyntaxException ex) {
141                 this.path = path;
142             }
143         }
144     }
145 
146     /**
147      * Creates request message with the given method, host and request path.
148      *
149      * @param method request method.
150      * @param host request host.
151      * @param path request path.
152      *
153      * @since 5.0
154      */
155     public BasicHttpRequest(final Method method, final HttpHost host, final String path) {
156         super();
157         this.method = Args.notNull(method, "Method").name();
158         this.scheme = host != null ? host.getSchemeName() : null;
159         this.authority = host != null ? new URIAuthority(host) : null;
160         this.path = path;
161     }
162 
163     /**
164      * Creates request message with the given method, request URI.
165      *
166      * @param method request method.
167      * @param requestUri request URI.
168      *
169      * @since 5.0
170      */
171     public BasicHttpRequest(final Method method, final URI requestUri) {
172         super();
173         this.method = Args.notNull(method, "Method").name();
174         setUri(Args.notNull(requestUri, "Request URI"));
175     }
176 
177     @Override
178     public void addHeader(final String name, final Object value) {
179         Args.notNull(name, "Header name");
180         addHeader(new BasicHeader(name, value));
181     }
182 
183     @Override
184     public void setHeader(final String name, final Object value) {
185         Args.notNull(name, "Header name");
186         setHeader(new BasicHeader(name, value));
187     }
188 
189     @Override
190     public void setVersion(final ProtocolVersion version) {
191         this.version = version;
192     }
193 
194     @Override
195     public ProtocolVersion getVersion() {
196         return this.version;
197     }
198 
199     @Override
200     public String getMethod() {
201         return this.method;
202     }
203 
204     @Override
205     public String getPath() {
206         return this.path;
207     }
208 
209     @Override
210     public void setPath(final String path) {
211         if (path != null) {
212             Args.check(!path.startsWith("//"), "URI path begins with multiple slashes");
213         }
214         this.path = path;
215         this.requestUri = null;
216     }
217 
218     @Override
219     public String getScheme() {
220         return this.scheme;
221     }
222 
223     @Override
224     public void setScheme(final String scheme) {
225         this.scheme = scheme;
226         this.requestUri = null;
227     }
228 
229     @Override
230     public URIAuthority getAuthority() {
231         return this.authority;
232     }
233 
234     @Override
235     public void setAuthority(final URIAuthority authority) {
236         this.authority = authority;
237         this.requestUri = null;
238     }
239 
240     /**
241      * Sets a flag that the {@link #getRequestUri()} method should return the request URI
242      * in an absolute form.
243      * <p>
244      * This flag can used when the request is going to be transmitted via an HTTP/1.1 proxy.
245      *
246      * @since 5.1
247      */
248     public void setAbsoluteRequestUri(final boolean absoluteRequestUri) {
249         this.absoluteRequestUri = absoluteRequestUri;
250     }
251 
252     @Override
253     public String getRequestUri() {
254         if (absoluteRequestUri) {
255             final StringBuilder buf = new StringBuilder();
256             assembleRequestUri(buf);
257             return buf.toString();
258         } else {
259             return getPath();
260         }
261     }
262 
263     @Override
264     public void setUri(final URI requestUri) {
265         this.scheme = requestUri.getScheme();
266         if (requestUri.getHost() != null) {
267             this.authority = new URIAuthority(
268                     requestUri.getRawUserInfo(), requestUri.getHost(), requestUri.getPort());
269         } else if (requestUri.getRawAuthority() != null) {
270             try {
271                 this.authority = URIAuthority.create(requestUri.getRawAuthority());
272             } catch (final URISyntaxException ignore) {
273                 this.authority = null;
274             }
275         } else {
276             this.authority = null;
277         }
278         final StringBuilder buf = new StringBuilder();
279         final String rawPath = requestUri.getRawPath();
280         if (!TextUtils.isBlank(rawPath)) {
281             Args.check(!rawPath.startsWith("//"), "URI path begins with multiple slashes");
282             buf.append(rawPath);
283         } else {
284             buf.append("/");
285         }
286         final String query = requestUri.getRawQuery();
287         if (query != null) {
288             buf.append('?').append(query);
289         }
290         this.path = buf.toString();
291     }
292 
293     private void assembleRequestUri(final StringBuilder buf) {
294         if (this.authority != null) {
295             buf.append(this.scheme != null ? this.scheme : URIScheme.HTTP.id).append("://");
296             buf.append(this.authority.getHostName());
297             if (this.authority.getPort() >= 0) {
298                 buf.append(":").append(this.authority.getPort());
299             }
300         }
301         if (this.path == null) {
302             buf.append("/");
303         } else {
304             if (buf.length() > 0 && !this.path.startsWith("/")) {
305                 buf.append("/");
306             }
307             buf.append(this.path);
308         }
309     }
310 
311     @Override
312     public URI getUri() throws URISyntaxException {
313         if (this.requestUri == null) {
314             final StringBuilder buf = new StringBuilder();
315             assembleRequestUri(buf);
316             this.requestUri = new URI(buf.toString());
317         }
318         return this.requestUri;
319     }
320 
321     @Override
322     public String toString() {
323         final StringBuilder buf = new StringBuilder();
324         buf.append(method).append(" ");
325         assembleRequestUri(buf);
326         return buf.toString();
327     }
328 
329 }