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.io.support;
29  
30  import java.net.URI;
31  import java.net.URISyntaxException;
32  import java.nio.charset.Charset;
33  import java.util.ArrayList;
34  import java.util.Iterator;
35  import java.util.LinkedList;
36  import java.util.List;
37  
38  import org.apache.hc.core5.http.ClassicHttpRequest;
39  import org.apache.hc.core5.http.ContentType;
40  import org.apache.hc.core5.http.Header;
41  import org.apache.hc.core5.http.HttpEntity;
42  import org.apache.hc.core5.http.HttpVersion;
43  import org.apache.hc.core5.http.Method;
44  import org.apache.hc.core5.http.NameValuePair;
45  import org.apache.hc.core5.http.ProtocolVersion;
46  import org.apache.hc.core5.http.io.entity.ByteArrayEntity;
47  import org.apache.hc.core5.http.io.entity.HttpEntities;
48  import org.apache.hc.core5.http.io.entity.StringEntity;
49  import org.apache.hc.core5.http.message.BasicClassicHttpRequest;
50  import org.apache.hc.core5.http.message.BasicHeader;
51  import org.apache.hc.core5.http.message.BasicNameValuePair;
52  import org.apache.hc.core5.http.message.HeaderGroup;
53  import org.apache.hc.core5.net.URIBuilder;
54  import org.apache.hc.core5.util.Args;
55  
56  /**
57   * Builder for {@link ClassicHttpRequest} instances.
58   * <p>
59   * Please note that this class treats parameters differently depending on composition
60   * of the request: if the request has a content entity explicitly set with
61   * {@link #setEntity(HttpEntity)} or it is not an entity enclosing method
62   * (such as POST or PUT), parameters will be added to the query component
63   * of the request URI. Otherwise, parameters will be added as a URL encoded entity.
64   * </p>
65   *
66   * @since 5.0
67   */
68  public class ClassicRequestBuilder {
69  
70      private String method;
71      private URI uri;
72      private Charset charset;
73      private ProtocolVersion version;
74      private HeaderGroup headerGroup;
75      private HttpEntity entity;
76      private List<NameValuePair> parameters;
77  
78      ClassicRequestBuilder() {
79      }
80  
81      ClassicRequestBuilder(final String method) {
82          super();
83          this.method = method;
84      }
85  
86      ClassicRequestBuilder(final Method method) {
87          this(method.name());
88      }
89  
90      ClassicRequestBuilder(final String method, final URI uri) {
91          super();
92          this.method = method;
93          this.uri = uri;
94      }
95  
96      ClassicRequestBuilder(final Method method, final URI uri) {
97          this(method.name(), uri);
98      }
99  
100     ClassicRequestBuilder(final Method method, final String uri) {
101         this(method.name(), uri != null ? URI.create(uri) : null);
102     }
103 
104     ClassicRequestBuilder(final String method, final String uri) {
105         this(method, uri != null ? URI.create(uri) : null);
106     }
107 
108     public static ClassicRequestBuilder create(final String method) {
109         Args.notBlank(method, "HTTP method");
110         return new ClassicRequestBuilder(method);
111     }
112 
113     public static ClassicRequestBuilder get() {
114         return new ClassicRequestBuilder(Method.GET);
115     }
116 
117     public static ClassicRequestBuilder get(final URI uri) {
118         return new ClassicRequestBuilder(Method.GET, uri);
119     }
120 
121     public static ClassicRequestBuilder get(final String uri) {
122         return new ClassicRequestBuilder(Method.GET, uri);
123     }
124 
125     public static ClassicRequestBuilder head() {
126         return new ClassicRequestBuilder(Method.HEAD);
127     }
128 
129     public static ClassicRequestBuilder head(final URI uri) {
130         return new ClassicRequestBuilder(Method.HEAD, uri);
131     }
132 
133     public static ClassicRequestBuilder head(final String uri) {
134         return new ClassicRequestBuilder(Method.HEAD, uri);
135     }
136 
137     public static ClassicRequestBuilder patch() {
138         return new ClassicRequestBuilder(Method.PATCH);
139     }
140 
141     public static ClassicRequestBuilder patch(final URI uri) {
142         return new ClassicRequestBuilder(Method.PATCH, uri);
143     }
144 
145     public static ClassicRequestBuilder patch(final String uri) {
146         return new ClassicRequestBuilder(Method.PATCH, uri);
147     }
148 
149     public static ClassicRequestBuilder post() {
150         return new ClassicRequestBuilder(Method.POST);
151     }
152 
153     public static ClassicRequestBuilder post(final URI uri) {
154         return new ClassicRequestBuilder(Method.POST, uri);
155     }
156 
157     public static ClassicRequestBuilder post(final String uri) {
158         return new ClassicRequestBuilder(Method.POST, uri);
159     }
160 
161     public static ClassicRequestBuilder put() {
162         return new ClassicRequestBuilder(Method.PUT);
163     }
164 
165     public static ClassicRequestBuilder put(final URI uri) {
166         return new ClassicRequestBuilder(Method.PUT, uri);
167     }
168 
169     public static ClassicRequestBuilder put(final String uri) {
170         return new ClassicRequestBuilder(Method.PUT, uri);
171     }
172 
173     public static ClassicRequestBuilder delete() {
174         return new ClassicRequestBuilder(Method.DELETE);
175     }
176 
177     public static ClassicRequestBuilder delete(final URI uri) {
178         return new ClassicRequestBuilder(Method.DELETE, uri);
179     }
180 
181     public static ClassicRequestBuilder delete(final String uri) {
182         return new ClassicRequestBuilder(Method.DELETE, uri);
183     }
184 
185     public static ClassicRequestBuilder trace() {
186         return new ClassicRequestBuilder(Method.TRACE);
187     }
188 
189     public static ClassicRequestBuilder trace(final URI uri) {
190         return new ClassicRequestBuilder(Method.TRACE, uri);
191     }
192 
193     public static ClassicRequestBuilder trace(final String uri) {
194         return new ClassicRequestBuilder(Method.TRACE, uri);
195     }
196 
197     public static ClassicRequestBuilder options() {
198         return new ClassicRequestBuilder(Method.OPTIONS);
199     }
200 
201     public static ClassicRequestBuilder options(final URI uri) {
202         return new ClassicRequestBuilder(Method.OPTIONS, uri);
203     }
204 
205     public static ClassicRequestBuilder options(final String uri) {
206         return new ClassicRequestBuilder(Method.OPTIONS, uri);
207     }
208 
209     public ClassicRequestBuilder setCharset(final Charset charset) {
210         this.charset = charset;
211         return this;
212     }
213 
214     public Charset getCharset() {
215         return charset;
216     }
217 
218     public String getMethod() {
219         return method;
220     }
221 
222     public ProtocolVersion getVersion() {
223         return version;
224     }
225 
226     public ClassicRequestBuilder setVersion(final ProtocolVersion version) {
227         this.version = version;
228         return this;
229     }
230 
231     public URI getUri() {
232         return uri;
233     }
234 
235     public ClassicRequestBuilder setUri(final URI uri) {
236         this.uri = uri;
237         return this;
238     }
239 
240     public ClassicRequestBuilder setUri(final String uri) {
241         this.uri = uri != null ? URI.create(uri) : null;
242         return this;
243     }
244 
245     public Header[] getHeaders(final String name) {
246         return headerGroup != null ? headerGroup.getHeaders(name) : null;
247     }
248 
249     public ClassicRequestBuilder setHeaders(final Header... headers) {
250         if (headerGroup == null) {
251             headerGroup = new HeaderGroup();
252         }
253         headerGroup.setHeaders(headers);
254         return this;
255     }
256 
257     public Header getFirstHeader(final String name) {
258         return headerGroup != null ? headerGroup.getFirstHeader(name) : null;
259     }
260 
261     public Header getLastHeader(final String name) {
262         return headerGroup != null ? headerGroup.getLastHeader(name) : null;
263     }
264 
265     public ClassicRequestBuilder addHeader(final Header header) {
266         if (headerGroup == null) {
267             headerGroup = new HeaderGroup();
268         }
269         headerGroup.addHeader(header);
270         return this;
271     }
272 
273     public ClassicRequestBuilder addHeader(final String name, final String value) {
274         if (headerGroup == null) {
275             headerGroup = new HeaderGroup();
276         }
277         this.headerGroup.addHeader(new BasicHeader(name, value));
278         return this;
279     }
280 
281     public ClassicRequestBuilder removeHeader(final Header header) {
282         if (headerGroup == null) {
283             headerGroup = new HeaderGroup();
284         }
285         headerGroup.removeHeader(header);
286         return this;
287     }
288 
289     public ClassicRequestBuilder removeHeaders(final String name) {
290         if (name == null || headerGroup == null) {
291             return this;
292         }
293         for (final Iterator<Header> i = headerGroup.headerIterator(); i.hasNext(); ) {
294             final Header header = i.next();
295             if (name.equalsIgnoreCase(header.getName())) {
296                 i.remove();
297             }
298         }
299         return this;
300     }
301 
302     public ClassicRequestBuilder setHeader(final Header header) {
303         if (headerGroup == null) {
304             headerGroup = new HeaderGroup();
305         }
306         this.headerGroup.setHeader(header);
307         return this;
308     }
309 
310     public ClassicRequestBuilder setHeader(final String name, final String value) {
311         if (headerGroup == null) {
312             headerGroup = new HeaderGroup();
313         }
314         this.headerGroup.setHeader(new BasicHeader(name, value));
315         return this;
316     }
317 
318     public HttpEntity getEntity() {
319         return entity;
320     }
321 
322     public ClassicRequestBuilder setEntity(final HttpEntity entity) {
323         this.entity = entity;
324         return this;
325     }
326 
327     public ClassicRequestBuilder setEntity(final String content, final ContentType contentType) {
328         this.entity = new StringEntity(content, contentType);
329         return this;
330     }
331 
332     public ClassicRequestBuilder setEntity(final String content) {
333         this.entity = new StringEntity(content);
334         return this;
335     }
336 
337     public ClassicRequestBuilder setEntity(final byte[] content, final ContentType contentType) {
338         this.entity = new ByteArrayEntity(content, contentType);
339         return this;
340     }
341 
342     public List<NameValuePair> getParameters() {
343         return parameters != null ? new ArrayList<>(parameters) :
344                 new ArrayList<NameValuePair>();
345     }
346 
347     public ClassicRequestBuilder addParameter(final NameValuePair nvp) {
348         Args.notNull(nvp, "Name value pair");
349         if (parameters == null) {
350             parameters = new LinkedList<>();
351         }
352         parameters.add(nvp);
353         return this;
354     }
355 
356     public ClassicRequestBuilder addParameter(final String name, final String value) {
357         return addParameter(new BasicNameValuePair(name, value));
358     }
359 
360     public ClassicRequestBuilder addParameters(final NameValuePair... nvps) {
361         for (final NameValuePair nvp : nvps) {
362             addParameter(nvp);
363         }
364         return this;
365     }
366 
367     public ClassicHttpRequest build() {
368         URI uriCopy = this.uri != null ? this.uri : URI.create("/");
369         HttpEntity entityCopy = this.entity;
370         if (parameters != null && !parameters.isEmpty()) {
371             if (entityCopy == null && (Method.POST.isSame(method) || Method.PUT.isSame(method))) {
372                 entityCopy = HttpEntities.createUrlEncoded(parameters, charset);
373             } else {
374                 try {
375                     uriCopy = new URIBuilder(uriCopy)
376                             .setCharset(this.charset)
377                             .addParameters(parameters)
378                             .build();
379                 } catch (final URISyntaxException ex) {
380                     // should never happen
381                 }
382             }
383         }
384 
385         if (entityCopy != null && Method.TRACE.isSame(method)) {
386             throw new IllegalStateException(Method.TRACE + " requests may not include an entity");
387         }
388 
389         final ClassicHttpRequest result = new BasicClassicHttpRequest(method, uriCopy);
390         result.setVersion(this.version != null ? this.version : HttpVersion.HTTP_1_1);
391         if (this.headerGroup != null) {
392             result.setHeaders(this.headerGroup.getHeaders());
393         }
394         result.setEntity(entityCopy);
395         return result;
396     }
397 
398     @Override
399     public String toString() {
400         final StringBuilder builder = new StringBuilder();
401         builder.append("ClassicRequestBuilder [method=");
402         builder.append(method);
403         builder.append(", charset=");
404         builder.append(charset);
405         builder.append(", version=");
406         builder.append(version);
407         builder.append(", uri=");
408         builder.append(uri);
409         builder.append(", headerGroup=");
410         builder.append(headerGroup);
411         builder.append(", entity=");
412         builder.append(entity != null ? entity.getClass() : null);
413         builder.append(", parameters=");
414         builder.append(parameters);
415         builder.append("]");
416         return builder.toString();
417     }
418 
419 }