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