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