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.http.client.methods;
29  
30  import java.io.IOException;
31  import java.net.URI;
32  import java.net.URISyntaxException;
33  import java.nio.charset.Charset;
34  import java.util.ArrayList;
35  import java.util.LinkedList;
36  import java.util.List;
37  
38  import org.apache.http.Consts;
39  import org.apache.http.Header;
40  import org.apache.http.HeaderIterator;
41  import org.apache.http.HttpEntity;
42  import org.apache.http.HttpEntityEnclosingRequest;
43  import org.apache.http.HttpRequest;
44  import org.apache.http.NameValuePair;
45  import org.apache.http.ProtocolVersion;
46  import org.apache.http.annotation.NotThreadSafe;
47  import org.apache.http.client.config.RequestConfig;
48  import org.apache.http.client.entity.UrlEncodedFormEntity;
49  import org.apache.http.client.utils.URIBuilder;
50  import org.apache.http.client.utils.URLEncodedUtils;
51  import org.apache.http.entity.ContentType;
52  import org.apache.http.message.BasicHeader;
53  import org.apache.http.message.BasicNameValuePair;
54  import org.apache.http.message.HeaderGroup;
55  import org.apache.http.protocol.HTTP;
56  import org.apache.http.util.Args;
57  
58  /**
59   * Builder for {@link HttpUriRequest} instances.
60   * <p/>
61   * Please note that this class treats parameters differently depending on composition
62   * of the request: if the request has a content entity explicitly set with
63   * {@link #setEntity(org.apache.http.HttpEntity)} or it is not an entity enclosing method
64   * (such as POST or PUT), parameters will be added to the query component of the request URI.
65   * Otherwise, parameters will be added as a URL encoded {@link UrlEncodedFormEntity entity}.
66   *
67   * @since 4.3
68   */
69  @NotThreadSafe
70  public class RequestBuilder {
71  
72      private String method;
73      private Charset charset;
74      private ProtocolVersion version;
75      private URI uri;
76      private HeaderGroup headergroup;
77      private HttpEntity entity;
78      private List<NameValuePair> parameters;
79      private RequestConfig config;
80  
81      RequestBuilder(final String method) {
82          super();
83          this.charset = Consts.UTF_8;
84          this.method = method;
85      }
86  
87      RequestBuilder(final String method, final URI uri) {
88          super();
89          this.method = method;
90          this.uri = uri;
91      }
92  
93      RequestBuilder(final String method, final String uri) {
94          super();
95          this.method = method;
96          this.uri = uri != null ? URI.create(uri) : null;
97      }
98  
99      RequestBuilder() {
100         this(null);
101     }
102 
103     public static RequestBuilder create(final String method) {
104         Args.notBlank(method, "HTTP method");
105         return new RequestBuilder(method);
106     }
107 
108     public static RequestBuilder get() {
109         return new RequestBuilder(HttpGet.METHOD_NAME);
110     }
111 
112     /**
113      * @since 4.4
114      */
115     public static RequestBuilder get(final URI uri) {
116         return new RequestBuilder(HttpGet.METHOD_NAME, uri);
117     }
118 
119     /**
120      * @since 4.4
121      */
122     public static RequestBuilder get(final String uri) {
123         return new RequestBuilder(HttpGet.METHOD_NAME, uri);
124     }
125 
126     public static RequestBuilder head() {
127         return new RequestBuilder(HttpHead.METHOD_NAME);
128     }
129 
130     /**
131      * @since 4.4
132      */
133     public static RequestBuilder head(final URI uri) {
134         return new RequestBuilder(HttpHead.METHOD_NAME, uri);
135     }
136 
137     /**
138      * @since 4.4
139      */
140     public static RequestBuilder head(final String uri) {
141         return new RequestBuilder(HttpHead.METHOD_NAME, uri);
142     }
143 
144     public static RequestBuilder post() {
145         return new RequestBuilder(HttpPost.METHOD_NAME);
146     }
147 
148     /**
149      * @since 4.4
150      */
151     public static RequestBuilder post(final URI uri) {
152         return new RequestBuilder(HttpPost.METHOD_NAME, uri);
153     }
154 
155     /**
156      * @since 4.4
157      */
158     public static RequestBuilder post(final String uri) {
159         return new RequestBuilder(HttpPost.METHOD_NAME, uri);
160     }
161 
162     public static RequestBuilder put() {
163         return new RequestBuilder(HttpPut.METHOD_NAME);
164     }
165 
166     /**
167      * @since 4.4
168      */
169     public static RequestBuilder put(final URI uri) {
170         return new RequestBuilder(HttpPut.METHOD_NAME, uri);
171     }
172 
173     /**
174      * @since 4.4
175      */
176     public static RequestBuilder put(final String uri) {
177         return new RequestBuilder(HttpPut.METHOD_NAME, uri);
178     }
179 
180     public static RequestBuilder delete() {
181         return new RequestBuilder(HttpDelete.METHOD_NAME);
182     }
183 
184     /**
185      * @since 4.4
186      */
187     public static RequestBuilder delete(final URI uri) {
188         return new RequestBuilder(HttpDelete.METHOD_NAME, uri);
189     }
190 
191     /**
192      * @since 4.4
193      */
194     public static RequestBuilder delete(final String uri) {
195         return new RequestBuilder(HttpDelete.METHOD_NAME, uri);
196     }
197 
198     public static RequestBuilder trace() {
199         return new RequestBuilder(HttpTrace.METHOD_NAME);
200     }
201 
202     /**
203      * @since 4.4
204      */
205     public static RequestBuilder trace(final URI uri) {
206         return new RequestBuilder(HttpTrace.METHOD_NAME, uri);
207     }
208 
209     /**
210      * @since 4.4
211      */
212     public static RequestBuilder trace(final String uri) {
213         return new RequestBuilder(HttpTrace.METHOD_NAME, uri);
214     }
215 
216     public static RequestBuilder options() {
217         return new RequestBuilder(HttpOptions.METHOD_NAME);
218     }
219 
220     /**
221      * @since 4.4
222      */
223     public static RequestBuilder options(final URI uri) {
224         return new RequestBuilder(HttpOptions.METHOD_NAME, uri);
225     }
226 
227     /**
228      * @since 4.4
229      */
230     public static RequestBuilder options(final String uri) {
231         return new RequestBuilder(HttpOptions.METHOD_NAME, uri);
232     }
233 
234     public static RequestBuilder copy(final HttpRequest request) {
235         Args.notNull(request, "HTTP request");
236         return new RequestBuilder().doCopy(request);
237     }
238 
239     private RequestBuilder doCopy(final HttpRequest request) {
240         if (request == null) {
241             return this;
242         }
243         method = request.getRequestLine().getMethod();
244         version = request.getRequestLine().getProtocolVersion();
245 
246         if (headergroup == null) {
247             headergroup = new HeaderGroup();
248         }
249         headergroup.clear();
250         headergroup.setHeaders(request.getAllHeaders());
251 
252         parameters = null;
253         entity = null;
254 
255         if (request instanceof HttpEntityEnclosingRequest) {
256             final HttpEntity originalEntity = ((HttpEntityEnclosingRequest) request).getEntity();
257             final ContentType contentType = ContentType.get(originalEntity);
258             if (contentType != null &&
259                     contentType.getMimeType().equals(ContentType.APPLICATION_FORM_URLENCODED.getMimeType())) {
260                 try {
261                     final List<NameValuePair> formParams = URLEncodedUtils.parse(originalEntity);
262                     if (!formParams.isEmpty()) {
263                         parameters = formParams;
264                     }
265                 } catch (IOException ignore) {
266                 }
267             } else {
268                 entity = originalEntity;
269             }
270         }
271 
272         final URI originalUri;
273         if (request instanceof HttpUriRequest) {
274             originalUri = ((HttpUriRequest) request).getURI();
275         } else {
276             originalUri = URI.create(request.getRequestLine().getUri());
277         }
278 
279         final URIBuilder uriBuilder = new URIBuilder(originalUri);
280         if (parameters == null) {
281             final List<NameValuePair> queryParams = uriBuilder.getQueryParams();
282             if (!queryParams.isEmpty()) {
283                 parameters = queryParams;
284                 uriBuilder.clearParameters();
285             } else {
286                 parameters = null;
287             }
288         }
289         try {
290             uri = uriBuilder.build();
291         } catch (URISyntaxException ex) {
292             // Should never happen
293             uri = originalUri;
294         }
295 
296         if (request instanceof Configurable) {
297             config = ((Configurable) request).getConfig();
298         } else {
299             config = null;
300         }
301         return this;
302     }
303 
304     /**
305      * @since 4.4
306      */
307     public RequestBuilder setCharset(final Charset charset) {
308         this.charset = charset;
309         return this;
310     }
311 
312     /**
313      * @since 4.4
314      */
315     public Charset getCharset() {
316         return charset;
317     }
318 
319     public String getMethod() {
320         return method;
321     }
322 
323     public ProtocolVersion getVersion() {
324         return version;
325     }
326 
327     public RequestBuilder setVersion(final ProtocolVersion version) {
328         this.version = version;
329         return this;
330     }
331 
332     public URI getUri() {
333         return uri;
334     }
335 
336     public RequestBuilder setUri(final URI uri) {
337         this.uri = uri;
338         return this;
339     }
340 
341     public RequestBuilder setUri(final String uri) {
342         this.uri = uri != null ? URI.create(uri) : null;
343         return this;
344     }
345 
346     public Header getFirstHeader(final String name) {
347         return headergroup != null ? headergroup.getFirstHeader(name) : null;
348     }
349 
350     public Header getLastHeader(final String name) {
351         return headergroup != null ? headergroup.getLastHeader(name) : null;
352     }
353 
354     public Header[] getHeaders(final String name) {
355         return headergroup != null ? headergroup.getHeaders(name) : null;
356     }
357 
358     public RequestBuilder addHeader(final Header header) {
359         if (headergroup == null) {
360             headergroup = new HeaderGroup();
361         }
362         headergroup.addHeader(header);
363         return this;
364     }
365 
366     public RequestBuilder addHeader(final String name, final String value) {
367         if (headergroup == null) {
368             headergroup = new HeaderGroup();
369         }
370         this.headergroup.addHeader(new BasicHeader(name, value));
371         return this;
372     }
373 
374     public RequestBuilder removeHeader(final Header header) {
375         if (headergroup == null) {
376             headergroup = new HeaderGroup();
377         }
378         headergroup.removeHeader(header);
379         return this;
380     }
381 
382     public RequestBuilder removeHeaders(final String name) {
383         if (name == null || headergroup == null) {
384             return this;
385         }
386         for (final HeaderIterator i = headergroup.iterator(); i.hasNext(); ) {
387             final Header header = i.nextHeader();
388             if (name.equalsIgnoreCase(header.getName())) {
389                 i.remove();
390             }
391         }
392         return this;
393     }
394 
395     public RequestBuilder setHeader(final Header header) {
396         if (headergroup == null) {
397             headergroup = new HeaderGroup();
398         }
399         this.headergroup.updateHeader(header);
400         return this;
401     }
402 
403     public RequestBuilder setHeader(final String name, final String value) {
404         if (headergroup == null) {
405             headergroup = new HeaderGroup();
406         }
407         this.headergroup.updateHeader(new BasicHeader(name, value));
408         return this;
409     }
410 
411     public HttpEntity getEntity() {
412         return entity;
413     }
414 
415     public RequestBuilder setEntity(final HttpEntity entity) {
416         this.entity = entity;
417         return this;
418     }
419 
420     public List<NameValuePair> getParameters() {
421         return parameters != null ? new ArrayList<NameValuePair>(parameters) :
422             new ArrayList<NameValuePair>();
423     }
424 
425     public RequestBuilder addParameter(final NameValuePair nvp) {
426         Args.notNull(nvp, "Name value pair");
427         if (parameters == null) {
428             parameters = new LinkedList<NameValuePair>();
429         }
430         parameters.add(nvp);
431         return this;
432     }
433 
434     public RequestBuilder addParameter(final String name, final String value) {
435         return addParameter(new BasicNameValuePair(name, value));
436     }
437 
438     public RequestBuilder addParameters(final NameValuePair... nvps) {
439         for (final NameValuePair nvp: nvps) {
440             addParameter(nvp);
441         }
442         return this;
443     }
444 
445     public RequestConfig getConfig() {
446         return config;
447     }
448 
449     public RequestBuilder setConfig(final RequestConfig config) {
450         this.config = config;
451         return this;
452     }
453 
454     public HttpUriRequest build() {
455         final HttpRequestBase result;
456         URI uriNotNull = this.uri != null ? this.uri : URI.create("/");
457         HttpEntity entityCopy = this.entity;
458         if (parameters != null && !parameters.isEmpty()) {
459             if (entityCopy == null && (HttpPost.METHOD_NAME.equalsIgnoreCase(method)
460                     || HttpPut.METHOD_NAME.equalsIgnoreCase(method))) {
461                 entityCopy = new UrlEncodedFormEntity(parameters, HTTP.DEF_CONTENT_CHARSET);
462             } else {
463                 try {
464                     uriNotNull = new URIBuilder(uriNotNull)
465                       .setCharset(this.charset)
466                       .addParameters(parameters)
467                       .build();
468                 } catch (final URISyntaxException ex) {
469                     // should never happen
470                 }
471             }
472         }
473         if (entityCopy == null) {
474             result = new InternalRequest(method);
475         } else {
476             final InternalEntityEclosingRequest request = new InternalEntityEclosingRequest(method);
477             request.setEntity(entityCopy);
478             result = request;
479         }
480         result.setProtocolVersion(this.version);
481         result.setURI(uriNotNull);
482         if (this.headergroup != null) {
483             result.setHeaders(this.headergroup.getAllHeaders());
484         }
485         result.setConfig(this.config);
486         return result;
487     }
488 
489     static class InternalRequest extends HttpRequestBase {
490 
491         private final String method;
492 
493         InternalRequest(final String method) {
494             super();
495             this.method = method;
496         }
497 
498         @Override
499         public String getMethod() {
500             return this.method;
501         }
502 
503     }
504 
505     static class InternalEntityEclosingRequest extends HttpEntityEnclosingRequestBase {
506 
507         private final String method;
508 
509         InternalEntityEclosingRequest(final String method) {
510             super();
511             this.method = method;
512         }
513 
514         @Override
515         public String getMethod() {
516             return this.method;
517         }
518 
519     }
520 
521 }