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  package org.apache.hc.client5.http.fluent;
28  
29  import java.io.File;
30  import java.io.IOException;
31  import java.io.InputStream;
32  import java.net.URI;
33  import java.net.URISyntaxException;
34  import java.nio.charset.Charset;
35  import java.nio.charset.StandardCharsets;
36  import java.time.Instant;
37  import java.util.ArrayList;
38  import java.util.Arrays;
39  import java.util.Date;
40  import java.util.List;
41  import java.util.Locale;
42  import java.util.TimeZone;
43  
44  import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;
45  import org.apache.hc.client5.http.config.Configurable;
46  import org.apache.hc.client5.http.config.RequestConfig;
47  import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
48  import org.apache.hc.client5.http.protocol.HttpClientContext;
49  import org.apache.hc.client5.http.utils.DateUtils;
50  import org.apache.hc.core5.http.ClassicHttpRequest;
51  import org.apache.hc.core5.http.ClassicHttpResponse;
52  import org.apache.hc.core5.http.ContentType;
53  import org.apache.hc.core5.http.Header;
54  import org.apache.hc.core5.http.HttpEntity;
55  import org.apache.hc.core5.http.HttpHeaders;
56  import org.apache.hc.core5.http.HttpHost;
57  import org.apache.hc.core5.http.HttpVersion;
58  import org.apache.hc.core5.http.Method;
59  import org.apache.hc.core5.http.NameValuePair;
60  import org.apache.hc.core5.http.io.entity.ByteArrayEntity;
61  import org.apache.hc.core5.http.io.entity.FileEntity;
62  import org.apache.hc.core5.http.io.entity.InputStreamEntity;
63  import org.apache.hc.core5.http.message.BasicClassicHttpRequest;
64  import org.apache.hc.core5.net.WWWFormCodec;
65  import org.apache.hc.core5.util.Timeout;
66  
67  /**
68   * HTTP request used by the fluent facade.
69   *
70   * @since 4.2
71   */
72  public class Request {
73  
74      /**
75       * @deprecated This attribute is no longer supported as a part of the public API.
76       */
77      @Deprecated
78      public static final String DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss zzz";
79      /**
80       * @deprecated This attribute is no longer supported as a part of the public API.
81       */
82      @Deprecated
83      public static final Locale DATE_LOCALE = Locale.US;
84      /**
85       * @deprecated This attribute is no longer supported as a part of the public API.
86       */
87      @Deprecated
88      public static final TimeZone TIME_ZONE = TimeZone.getTimeZone("GMT");
89  
90      private final ClassicHttpRequest request;
91      private Boolean useExpectContinue;
92      private Timeout connectTimeout;
93      private Timeout responseTimeout;
94      private HttpHost proxy;
95  
96      public static Request create(final Method method, final URI uri) {
97        return new Request(new HttpUriRequestBase(method.name(), uri));
98    }
99  
100     public static Request create(final String methodName, final String uri) {
101         return new Request(new HttpUriRequestBase(methodName, URI.create(uri)));
102     }
103 
104     public static Request create(final String methodName, final URI uri) {
105       return new Request(new HttpUriRequestBase(methodName, uri));
106   }
107 
108     public static Request get(final URI uri) {
109        return new Request(new BasicClassicHttpRequest(Method.GET, uri));
110     }
111 
112     public static Request get(final String uri) {
113         return new Request(new BasicClassicHttpRequest(Method.GET, uri));
114     }
115 
116     public static Request head(final URI uri) {
117         return new Request(new BasicClassicHttpRequest(Method.HEAD, uri));
118     }
119 
120     public static Request head(final String uri) {
121         return new Request(new BasicClassicHttpRequest(Method.HEAD, uri));
122     }
123 
124     public static Request post(final URI uri) {
125         return new Request(new BasicClassicHttpRequest(Method.POST, uri));
126     }
127 
128     public static Request post(final String uri) {
129       return new Request(new BasicClassicHttpRequest(Method.POST, uri));
130     }
131 
132     public static Request patch(final URI uri) {
133       return new Request(new BasicClassicHttpRequest(Method.PATCH, uri));
134     }
135 
136     public static Request patch(final String uri) {
137       return new Request(new BasicClassicHttpRequest(Method.PATCH, uri));
138     }
139 
140     public static Request put(final URI uri) {
141       return new Request(new BasicClassicHttpRequest(Method.PUT, uri));
142     }
143 
144     public static Request put(final String uri) {
145       return new Request(new BasicClassicHttpRequest(Method.PUT, uri));
146     }
147 
148     public static Request trace(final URI uri) {
149       return new Request(new BasicClassicHttpRequest(Method.TRACE, uri));
150     }
151 
152     public static Request trace(final String uri) {
153       return new Request(new BasicClassicHttpRequest(Method.TRACE, uri));
154     }
155 
156     public static Request delete(final URI uri) {
157       return new Request(new BasicClassicHttpRequest(Method.DELETE, uri));
158     }
159 
160     public static Request delete(final String uri) {
161       return new Request(new BasicClassicHttpRequest(Method.DELETE, uri));
162     }
163 
164     public static Request options(final URI uri) {
165       return new Request(new BasicClassicHttpRequest(Method.OPTIONS, uri));
166     }
167 
168     public static Request options(final String uri) {
169       return new Request(new BasicClassicHttpRequest(Method.OPTIONS, uri));
170     }
171 
172     Request(final ClassicHttpRequest request) {
173         super();
174         this.request = request;
175     }
176 
177     @SuppressWarnings("deprecation")
178     ClassicHttpResponse internalExecute(
179             final CloseableHttpClient client,
180             final HttpClientContext localContext) throws IOException {
181         final RequestConfig.Builder builder;
182         if (client instanceof Configurable) {
183             builder = RequestConfig.copy(((Configurable) client).getConfig());
184         } else {
185             builder = RequestConfig.custom();
186         }
187         if (this.useExpectContinue != null) {
188             builder.setExpectContinueEnabled(this.useExpectContinue.booleanValue());
189         }
190         if (this.connectTimeout != null) {
191             builder.setConnectTimeout(this.connectTimeout);
192         }
193         if (this.responseTimeout != null) {
194             builder.setResponseTimeout(this.responseTimeout);
195         }
196         if (this.proxy != null) {
197             builder.setProxy(this.proxy);
198         }
199         final RequestConfig config = builder.build();
200         localContext.setRequestConfig(config);
201         return client.executeOpen(null, this.request, localContext);
202     }
203 
204     public Response execute() throws IOException {
205         return execute(Executor.CLIENT);
206     }
207 
208     public Response execute(final CloseableHttpClient client) throws IOException {
209         return new Response(internalExecute(client, HttpClientContext.create()));
210     }
211 
212     //// HTTP header operations
213 
214     public Request addHeader(final Header header) {
215         this.request.addHeader(header);
216         return this;
217     }
218 
219     /**
220      * @since 4.3
221      */
222     public Request setHeader(final Header header) {
223         this.request.setHeader(header);
224         return this;
225     }
226 
227     public Request addHeader(final String name, final String value) {
228         this.request.addHeader(name, value);
229         return this;
230     }
231 
232     /**
233      * @since 4.3
234      */
235     public Request setHeader(final String name, final String value) {
236         this.request.setHeader(name, value);
237         return this;
238     }
239 
240     public Request removeHeader(final Header header) {
241         this.request.removeHeader(header);
242         return this;
243     }
244 
245     public Request removeHeaders(final String name) {
246         this.request.removeHeaders(name);
247         return this;
248     }
249 
250     public Request setHeaders(final Header... headers) {
251         this.request.setHeaders(headers);
252         return this;
253     }
254 
255     public Request setCacheControl(final String cacheControl) {
256         this.request.setHeader(HttpHeader.CACHE_CONTROL, cacheControl);
257         return this;
258     }
259 
260     ClassicHttpRequest getRequest() {
261       return request;
262     }
263 
264     /**
265      * @deprecated Use {@link #setDate(Instant)}
266      */
267     @Deprecated
268     public Request setDate(final Date date) {
269         this.request.setHeader(HttpHeader.DATE, DateUtils.formatStandardDate(DateUtils.toInstant(date)));
270         return this;
271     }
272 
273     /**
274      * @deprecated Use {@link #setIfModifiedSince(Instant)}
275      */
276     @Deprecated
277     public Request setIfModifiedSince(final Date date) {
278         this.request.setHeader(HttpHeader.IF_MODIFIED_SINCE, DateUtils.formatStandardDate(DateUtils.toInstant(date)));
279         return this;
280     }
281 
282     /**
283      * @deprecated Use {@link #setIfUnmodifiedSince(Instant)}
284      */
285     @Deprecated
286     public Request setIfUnmodifiedSince(final Date date) {
287         this.request.setHeader(HttpHeader.IF_UNMODIFIED_SINCE, DateUtils.formatStandardDate(DateUtils.toInstant(date)));
288         return this;
289     }
290 
291     public Request setDate(final Instant instant) {
292         this.request.setHeader(HttpHeader.DATE, DateUtils.formatStandardDate(instant));
293         return this;
294     }
295 
296     public Request setIfModifiedSince(final Instant instant) {
297         this.request.setHeader(HttpHeader.IF_MODIFIED_SINCE, DateUtils.formatStandardDate(instant));
298         return this;
299     }
300 
301     public Request setIfUnmodifiedSince(final Instant instant) {
302         this.request.setHeader(HttpHeader.IF_UNMODIFIED_SINCE, DateUtils.formatStandardDate(instant));
303         return this;
304     }
305 
306     //// HTTP protocol parameter operations
307 
308     public Request version(final HttpVersion version) {
309         this.request.setVersion(version);
310         return this;
311     }
312 
313     public Request useExpectContinue() {
314         this.useExpectContinue = Boolean.TRUE;
315         return this;
316     }
317 
318     public Request userAgent(final String agent) {
319         this.request.setHeader(HttpHeaders.USER_AGENT, agent);
320         return this;
321     }
322 
323     //// HTTP connection parameter operations
324 
325     public Request connectTimeout(final Timeout timeout) {
326         this.connectTimeout = timeout;
327         return this;
328     }
329 
330     public Request responseTimeout(final Timeout timeout) {
331         this.responseTimeout = timeout;
332         return this;
333     }
334 
335     //// HTTP connection route operations
336 
337     public Request viaProxy(final HttpHost proxy) {
338         this.proxy = proxy;
339         return this;
340     }
341 
342     /**
343      * @since 4.4
344      */
345     public Request viaProxy(final String proxy) {
346         try {
347             this.proxy = HttpHost.create(proxy);
348         } catch (final URISyntaxException e) {
349             throw new IllegalArgumentException("Invalid host");
350         }
351         return this;
352     }
353 
354     //// HTTP entity operations
355 
356     public Request body(final HttpEntity entity) {
357         this.request.setEntity(entity);
358         return this;
359     }
360 
361     public Request bodyForm(final Iterable <? extends NameValuePair> formParams, final Charset charset) {
362         final List<NameValuePair> paramList = new ArrayList<>();
363         for (final NameValuePair param : formParams) {
364             paramList.add(param);
365         }
366         final ContentType contentType = charset != null ?
367                 ContentType.APPLICATION_FORM_URLENCODED.withCharset(charset) : ContentType.APPLICATION_FORM_URLENCODED;
368         final String s = WWWFormCodec.format(paramList, contentType.getCharset());
369         return bodyString(s, contentType);
370     }
371 
372     public Request bodyForm(final Iterable <? extends NameValuePair> formParams) {
373         return bodyForm(formParams, StandardCharsets.ISO_8859_1);
374     }
375 
376     public Request bodyForm(final NameValuePair... formParams) {
377         return bodyForm(Arrays.asList(formParams), StandardCharsets.ISO_8859_1);
378     }
379 
380     public Request bodyString(final String s, final ContentType contentType) {
381         final Charset charset = contentType != null ? contentType.getCharset() : null;
382         final byte[] raw = charset != null ? s.getBytes(charset) : s.getBytes();
383         return body(new ByteArrayEntity(raw, contentType));
384     }
385 
386     public Request bodyFile(final File file, final ContentType contentType) {
387         return body(new FileEntity(file, contentType));
388     }
389 
390     public Request bodyByteArray(final byte[] b) {
391         return body(new ByteArrayEntity(b, null));
392     }
393 
394     /**
395      * @since 4.4
396      */
397     public Request bodyByteArray(final byte[] b, final ContentType contentType) {
398         return body(new ByteArrayEntity(b, contentType));
399     }
400 
401     public Request bodyByteArray(final byte[] b, final int off, final int len) {
402         return body(new ByteArrayEntity(b, off, len, null));
403     }
404 
405     /**
406      * @since 4.4
407      */
408     public Request bodyByteArray(final byte[] b, final int off, final int len, final ContentType contentType) {
409         return body(new ByteArrayEntity(b, off, len, contentType));
410     }
411 
412     public Request bodyStream(final InputStream inStream) {
413         return body(new InputStreamEntity(inStream, -1, null));
414     }
415 
416     public Request bodyStream(final InputStream inStream, final ContentType contentType) {
417         return body(new InputStreamEntity(inStream, -1, contentType));
418     }
419 
420     @Override
421     public String toString() {
422         return this.request.toString();
423     }
424 
425 }