001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.rest.client2;
014
015import static org.apache.juneau.internal.StringUtils.*;
016import static org.apache.juneau.internal.ClassUtils.*;
017import static org.apache.juneau.AddFlag.*;
018import static org.apache.juneau.httppart.HttpPartType.*;
019
020import java.io.*;
021import java.lang.reflect.*;
022import java.net.*;
023import java.text.*;
024import java.util.*;
025import java.util.concurrent.*;
026import java.util.function.*;
027import java.util.logging.*;
028
029import org.apache.http.*;
030import org.apache.http.client.config.*;
031import org.apache.http.client.entity.*;
032import org.apache.http.client.methods.*;
033import org.apache.http.client.utils.*;
034import org.apache.http.concurrent.*;
035import org.apache.http.entity.*;
036import org.apache.http.entity.BasicHttpEntity;
037import org.apache.http.entity.ContentType;
038import org.apache.http.params.*;
039import org.apache.http.protocol.*;
040import org.apache.juneau.*;
041import org.apache.juneau.collections.*;
042import org.apache.juneau.html.*;
043import org.apache.juneau.http.*;
044import org.apache.juneau.http.header.*;
045import org.apache.juneau.httppart.*;
046import org.apache.juneau.internal.*;
047import org.apache.juneau.json.*;
048import org.apache.juneau.msgpack.*;
049import org.apache.juneau.oapi.*;
050import org.apache.juneau.parser.*;
051import org.apache.juneau.plaintext.*;
052import org.apache.juneau.serializer.*;
053import org.apache.juneau.uon.*;
054import org.apache.juneau.urlencoding.*;
055import org.apache.juneau.xml.*;
056
057/**
058 * Represents a request to a remote REST resource.
059 *
060 * <p>
061 * Instances of this class are created by the various creator methods on the {@link RestClient} class.
062 *
063 * <ul class='seealso'>
064 *    <li class='jc'>{@link RestClient}
065 *    <li class='link'>{@doc juneau-rest-client}
066 * </ul>
067 */
068public class RestRequest extends BeanSession implements HttpUriRequest, Configurable {
069
070   private static final ContentType TEXT_PLAIN = ContentType.create("text/plain");
071
072   private final RestClient client;                       // The client that created this call.
073   private final HttpRequestBase request;                 // The request.
074   private RestResponse response;                         // The response.
075   List<RestCallInterceptor> interceptors = new ArrayList<>();   // Used for intercepting and altering requests.
076
077   private boolean ignoreErrors;
078
079   private Object input;
080   private boolean hasInput;                              // input() was called, even if it's setting 'null'.
081   private Serializer serializer;
082   private Parser parser;
083   private HttpPartSerializerSession partSerializer;
084   private HttpPartSchema requestBodySchema;
085   private URIBuilder uriBuilder;
086   private List<NameValuePair> formData;
087   private Predicate<Integer> errorCodes;
088   private HttpHost target;
089   private HttpContext context;
090
091   /**
092    * Constructs a REST call with the specified method name.
093    *
094    * @param client The client that created this request.
095    * @param uri The target URI.
096    * @param method The HTTP method name (uppercase).
097    * @param hasBody Whether this method has a body.
098    * @throws RestCallException If an exception or non-200 response code occurred during the connection attempt.
099    */
100   protected RestRequest(RestClient client, URI uri, String method, boolean hasBody) throws RestCallException {
101      super(client, BeanSessionArgs.DEFAULT);
102      this.client = client;
103      this.request = createInnerRequest(method, uri, hasBody);
104      this.errorCodes = client.errorCodes;
105      this.partSerializer = client.getPartSerializerSession();
106      this.uriBuilder = new URIBuilder(request.getURI());
107      this.ignoreErrors = client.ignoreErrors;
108   }
109
110   /**
111    * Constructs the {@link HttpRequestBase} object that ends up being passed to the client execute method.
112    *
113    * <p>
114    * Subclasses can override this method to create their own request base objects.
115    *
116    * @param method The HTTP method.
117    * @param uri The HTTP URI.
118    * @param hasBody Whether the HTTP request has a body.
119    * @return A new {@link HttpRequestBase} object.
120    */
121   protected HttpRequestBase createInnerRequest(String method, URI uri, boolean hasBody) {
122      HttpRequestBase req = hasBody ? new BasicHttpEntityRequestBase(this, method) : new BasicHttpRequestBase(this, method);
123      req.setURI(uri);
124      return req;
125   }
126
127
128   //------------------------------------------------------------------------------------------------------------------
129   // Configuration
130   //------------------------------------------------------------------------------------------------------------------
131
132   /**
133    * Convenience method for specifying JSON as the marshalling transmission media type for this request only.
134    *
135    * <p>
136    * {@link JsonSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
137    *    <ul>
138    *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link RestClientBuilder#sortCollections()}),
139    *          bean context property setters (e.g. {@link RestClientBuilder#swaps(Object...)}), or generic property setters (e.g. {@link RestClientBuilder#set(String, Object)}) defined on this builder class.
140    *    </ul>
141    * <p>
142    *    {@link JsonParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
143    *    <ul>
144    *       <li>The parser can be configured using any of the parser property setters (e.g. {@link RestClientBuilder#strict()}),
145    *          bean context property setters (e.g. {@link RestClientBuilder#swaps(Object...)}), or generic property setters (e.g. {@link RestClientBuilder#set(String, Object)}) defined on this builder class.
146    *    </ul>
147    * <p>
148    *    <c>Accept</c> request header will be set to <js>"application/json"</js> unless overridden
149    *       by {@link RestRequest#header(String,Object)} or {@link RestRequest#accept(Object)}.
150    * <p>
151    *    <c>Content-Type</c> request header will be set to <js>"application/json"</js> unless overridden
152    *       {@link RestRequest#header(String,Object)} or {@link RestRequest#contentType(Object)}.
153    * <p>
154    *    Identical to calling <c>serializer(JsonSerializer.<jk>class</jk>).parser(JsonParser.<jk>class</jk>)</c>.
155    *
156    * @return This object (for method chaining).
157    */
158   public RestRequest json() {
159      return serializer(JsonSerializer.class).parser(JsonParser.class);
160   }
161
162   /**
163    * Convenience method for specifying Simplified JSON as the marshalling transmission media type for this request only.
164    *
165    * <p>
166    * Simplified JSON is typically useful for automated tests because you can do simple string comparison of results
167    * without having to escape lots of quotes.
168    *
169    * <p>
170    *    {@link SimpleJsonSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
171    *    <ul>
172    *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link RestClientBuilder#sortCollections()}),
173    *          bean context property setters (e.g. {@link RestClientBuilder#swaps(Object...)}), or generic property setters (e.g. {@link RestClientBuilder#set(String, Object)}) defined on this builder class.
174    *    </ul>
175    * <p>
176    *    {@link JsonParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
177    *    <ul>
178    *       <li>The parser can be configured using any of the parser property setters (e.g. {@link RestClientBuilder#strict()}),
179    *          bean context property setters (e.g. {@link RestClientBuilder#swaps(Object...)}), or generic property setters (e.g. {@link RestClientBuilder#set(String, Object)}) defined on this builder class.
180    *    </ul>
181    * <p>
182    *    <c>Accept</c> request header will be set to <js>"application/json"</js> unless overridden
183    *       by {@link #header(String,Object)} or {@link #accept(Object)}, or per-request via {@link RestRequest#header(String,Object)} or {@link RestRequest#accept(Object)}.
184    * <p>
185    *    <c>Content-Type</c> request header will be set to <js>"application/json+simple"</js> unless overridden
186    *       by {@link #header(String,Object)} or {@link #contentType(Object)}, or per-request via {@link RestRequest#header(String,Object)} or {@link RestRequest#contentType(Object)}.
187    * <p>
188    *    Can be combined with other marshaller setters such as {@link #xml()} to provide support for multiple languages.
189    *    <ul>
190    *       <li>When multiple languages are supported, the <c>Accept</c> and <c>Content-Type</c> headers control which marshallers are used, or uses the
191    *       last-enabled language if the headers are not set.
192    *    </ul>
193    * <p>
194    *    Identical to calling <c>serializer(SimpleJsonSerializer.<jk>class</jk>).parser(JsonParser.<jk>class</jk>)</c>.
195    *
196    * <h5 class='section'>Example:</h5>
197    * <p class='bcode w800'>
198    *    <jc>// Construct a client that uses Simplified JSON marshalling.</jc>
199    *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().simpleJson().build();
200    * </p>
201    *
202    * @return This object (for method chaining).
203    */
204   public RestRequest simpleJson() {
205      return serializer(SimpleJsonSerializer.class).parser(SimpleJsonParser.class);
206   }
207
208   /**
209    * Convenience method for specifying XML as the marshalling transmission media type for this request only.
210    *
211    * <p>
212    * {@link XmlSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
213    *    <ul>
214    *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link RestClientBuilder#sortCollections()}),
215    *          bean context property setters (e.g. {@link RestClientBuilder#swaps(Object...)}), or generic property setters (e.g. {@link RestClientBuilder#set(String, Object)}) defined on this builder class.
216    *    </ul>
217    * <p>
218    *    {@link XmlParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
219    *    <ul>
220    *       <li>The parser can be configured using any of the parser property setters (e.g. {@link RestClientBuilder#strict()}),
221    *          bean context property setters (e.g. {@link RestClientBuilder#swaps(Object...)}), or generic property setters (e.g. {@link RestClientBuilder#set(String, Object)}) defined on this builder class.
222    *    </ul>
223    * <p>
224    *    <c>Accept</c> request header will be set to <js>"text/xml"</js> unless overridden
225    *       by {@link RestRequest#header(String,Object)} or {@link RestRequest#accept(Object)}.
226    * <p>
227    *    <c>Content-Type</c> request header will be set to <js>"text/xml"</js> unless overridden
228    *       by {@link RestRequest#header(String,Object)} or {@link RestRequest#contentType(Object)}.
229    * <p>
230    *    Identical to calling <c>serializer(XmlSerializer.<jk>class</jk>).parser(XmlParser.<jk>class</jk>)</c>.
231    *
232    * <h5 class='section'>Example:</h5>
233    * <p class='bcode w800'>
234    *    <jc>// Construct a client that uses XML marshalling.</jc>
235    *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().xml().build();
236    * </p>
237    *
238    * @return This object (for method chaining).
239    */
240   public RestRequest xml() {
241      return serializer(XmlSerializer.class).parser(XmlParser.class);
242   }
243
244   /**
245    * Convenience method for specifying HTML as the marshalling transmission media type for this request only.
246    *
247    * <p>
248    * POJOs are converted to HTML without any sort of doc wrappers.
249    *
250    * <p>
251    *    {@link HtmlSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
252    *    <ul>
253    *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link RestClientBuilder#sortCollections()}),
254    *          bean context property setters (e.g. {@link RestClientBuilder#swaps(Object...)}), or generic property setters (e.g. {@link RestClientBuilder#set(String, Object)}) defined on this builder class.
255    *    </ul>
256    * <p>
257    *    {@link HtmlParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
258    *    <ul>
259    *       <li>The parser can be configured using any of the parser property setters (e.g. {@link RestClientBuilder#strict()}),
260    *          bean context property setters (e.g. {@link RestClientBuilder#swaps(Object...)}), or generic property setters (e.g. {@link RestClientBuilder#set(String, Object)}) defined on this builder class.
261    *    </ul>
262    * <p>
263    *    <c>Accept</c> request header will be set to <js>"text/html"</js> unless overridden
264    *       by {@link RestRequest#header(String,Object)} or {@link RestRequest#accept(Object)}.
265    * <p>
266    *    <c>Content-Type</c> request header will be set to <js>"text/html"</js> unless overridden
267    *       by {@link RestRequest#header(String,Object)} or {@link RestRequest#contentType(Object)}.
268    * <p>
269    *    Identical to calling <c>serializer(HtmlSerializer.<jk>class</jk>).parser(HtmlParser.<jk>class</jk>)</c>.
270    *
271    * <h5 class='section'>Example:</h5>
272    * <p class='bcode w800'>
273    *    <jc>// Construct a client that uses HTML marshalling.</jc>
274    *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().html().build();
275    * </p>
276    *
277    * @return This object (for method chaining).
278    */
279   public RestRequest html() {
280      return serializer(HtmlSerializer.class).parser(HtmlParser.class);
281   }
282
283   /**
284    * Convenience method for specifying HTML DOC as the marshalling transmission media type for this request only.
285    *
286    * <p>
287    * POJOs are converted to fully renderable HTML pages.
288    *
289    * <p>
290    *    {@link HtmlDocSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
291    *    <ul>
292    *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link RestClientBuilder#sortCollections()}),
293    *          bean context property setters (e.g. {@link RestClientBuilder#swaps(Object...)}), or generic property setters (e.g. {@link RestClientBuilder#set(String, Object)}) defined on this builder class.
294    *    </ul>
295    * <p>
296    *    {@link HtmlParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
297    *    <ul>
298    *       <li>The parser can be configured using any of the parser property setters (e.g. {@link RestClientBuilder#strict()}),
299    *          bean context property setters (e.g. {@link RestClientBuilder#swaps(Object...)}), or generic property setters (e.g. {@link RestClientBuilder#set(String, Object)}) defined on this builder class.
300    *    </ul>
301    * <p>
302    *    <c>Accept</c> request header will be set to <js>"text/html"</js> unless overridden
303    *       by {@link RestRequest#header(String,Object)} or {@link RestRequest#accept(Object)}.
304    * <p>
305    *    <c>Content-Type</c> request header will be set to <js>"text/html"</js> unless overridden
306    *       by {@link RestRequest#header(String,Object)} or {@link RestRequest#contentType(Object)}.
307    * <p>
308    *    Identical to calling <c>serializer(HtmlDocSerializer.<jk>class</jk>).parser(HtmlParser.<jk>class</jk>)</c>.
309    *
310    * <h5 class='section'>Example:</h5>
311    * <p class='bcode w800'>
312    *    <jc>// Construct a client that uses HTML Doc marshalling.</jc>
313    *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().htmlDoc().build();
314    * </p>
315    *
316    * @return This object (for method chaining).
317    */
318   public RestRequest htmlDoc() {
319      return serializer(HtmlDocSerializer.class).parser(HtmlParser.class);
320   }
321
322   /**
323    * Convenience method for specifying Stripped HTML DOC as the marshalling transmission media type for this request only.
324    *
325    * <p>
326    * Same as {@link #htmlDoc()} but without the header and body tags and page title and description.
327    *
328    * <p>
329    *    {@link HtmlStrippedDocSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
330    *    <ul>
331    *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link RestClientBuilder#sortCollections()}),
332    *          bean context property setters (e.g. {@link RestClientBuilder#swaps(Object...)}), or generic property setters (e.g. {@link RestClientBuilder#set(String, Object)}) defined on this builder class.
333    *    </ul>
334    * <p>
335    *    {@link HtmlParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
336    *    <ul>
337    *       <li>The parser can be configured using any of the parser property setters (e.g. {@link RestClientBuilder#strict()}),
338    *          bean context property setters (e.g. {@link RestClientBuilder#swaps(Object...)}), or generic property setters (e.g. {@link RestClientBuilder#set(String, Object)}) defined on this builder class.
339    *    </ul>
340    * <p>
341    *    <c>Accept</c> request header will be set to <js>"text/html+stripped"</js> unless overridden
342    *       by {@link RestRequest#header(String,Object)} or {@link RestRequest#accept(Object)}.
343    * <p>
344    *    <c>Content-Type</c> request header will be set to <js>"text/html+stripped"</js> unless overridden
345    *       by {@link RestRequest#header(String,Object)} or {@link RestRequest#contentType(Object)}.
346    * <p>
347    *    Identical to calling <c>serializer(HtmlStrippedDocSerializer.<jk>class</jk>).parser(HtmlParser.<jk>class</jk>)</c>.
348    *
349    * <h5 class='section'>Example:</h5>
350    * <p class='bcode w800'>
351    *    <jc>// Construct a client that uses HTML Stripped Doc marshalling.</jc>
352    *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().htmlStrippedDoc().build();
353    * </p>
354    *
355    * @return This object (for method chaining).
356    */
357   public RestRequest htmlStrippedDoc() {
358      return serializer(HtmlStrippedDocSerializer.class).parser(HtmlParser.class);
359   }
360
361   /**
362    * Convenience method for specifying Plain Text as the marshalling transmission media type for this request only.
363    *
364    * <p>
365    * Plain text marshalling typically only works on simple POJOs that can be converted to and from strings using
366    * swaps, swap methods, etc...
367    *
368    * <p>
369    *    {@link PlainTextSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
370    *    <ul>
371    *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link RestClientBuilder#sortCollections()}),
372    *          bean context property setters (e.g. {@link RestClientBuilder#swaps(Object...)}), or generic property setters (e.g. {@link RestClientBuilder#set(String, Object)}) defined on this builder class.
373    *    </ul>
374    * <p>
375    *    {@link PlainTextParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
376    *    <ul>
377    *       <li>The parser can be configured using any of the parser property setters (e.g. {@link RestClientBuilder#strict()}),
378    *          bean context property setters (e.g. {@link RestClientBuilder#swaps(Object...)}), or generic property setters (e.g. {@link RestClientBuilder#set(String, Object)}) defined on this builder class.
379    *    </ul>
380    * <p>
381    *    <c>Accept</c> request header will be set to <js>"text/plain"</js> unless overridden
382    *       by {@link RestRequest#header(String,Object)} or {@link RestRequest#accept(Object)}.
383    * <p>
384    *    <c>Content-Type</c> request header will be set to <js>"text/plain"</js> unless overridden
385    *       by {@link RestRequest#header(String,Object)} or {@link RestRequest#contentType(Object)}.
386    * <p>
387    *    Identical to calling <c>serializer(PlainTextSerializer.<jk>class</jk>).parser(PlainTextParser.<jk>class</jk>)</c>.
388    *
389    * <h5 class='section'>Example:</h5>
390    * <p class='bcode w800'>
391    *    <jc>// Construct a client that uses Plain Text marshalling.</jc>
392    *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().plainText().build();
393    * </p>
394    *
395    * @return This object (for method chaining).
396    */
397   public RestRequest plainText() {
398      return serializer(PlainTextSerializer.class).parser(PlainTextParser.class);
399   }
400
401   /**
402    * Convenience method for specifying MessagePack as the marshalling transmission media type for this request only.
403    *
404    * <p>
405    * MessagePack is a binary equivalent to JSON that takes up considerably less space than JSON.
406    *
407    * <p>
408    *    {@link MsgPackSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
409    *    <ul>
410    *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link RestClientBuilder#sortCollections()}),
411    *          bean context property setters (e.g. {@link RestClientBuilder#swaps(Object...)}), or generic property setters (e.g. {@link RestClientBuilder#set(String, Object)}) defined on this builder class.
412    *    </ul>
413    * <p>
414    *    {@link MsgPackParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
415    *    <ul>
416    *       <li>The parser can be configured using any of the parser property setters (e.g. {@link RestClientBuilder#strict()}),
417    *          bean context property setters (e.g. {@link RestClientBuilder#swaps(Object...)}), or generic property setters (e.g. {@link RestClientBuilder#set(String, Object)}) defined on this builder class.
418    *    </ul>
419    * <p>
420    *    <c>Accept</c> request header will be set to <js>"octal/msgpack"</js> unless overridden
421    *       by {@link RestRequest#header(String,Object)} or {@link RestRequest#accept(Object)}.
422    * <p>
423    *    <c>Content-Type</c> request header will be set to <js>"octal/msgpack"</js> unless overridden
424    *       by {@link RestRequest#header(String,Object)} or {@link RestRequest#contentType(Object)}.
425    * <p>
426    *    Identical to calling <c>serializer(MsgPackSerializer.<jk>class</jk>).parser(MsgPackParser.<jk>class</jk>)</c>.
427    *
428    * <h5 class='section'>Example:</h5>
429    * <p class='bcode w800'>
430    *    <jc>// Construct a client that uses MessagePack marshalling.</jc>
431    *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().msgPack().build();
432    * </p>
433    *
434    * @return This object (for method chaining).
435    */
436   public RestRequest msgPack() {
437      return serializer(MsgPackSerializer.class).parser(MsgPackParser.class);
438   }
439
440   /**
441    * Convenience method for specifying UON as the marshalling transmission media type for this request only.
442    *
443    * <p>
444    * UON is Url-Encoding Object notation that is equivalent to JSON but suitable for transmission as URL-encoded
445    * query and form post values.
446    *
447    * <p>
448    *    {@link UonSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
449    *    <ul>
450    *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link RestClientBuilder#sortCollections()}),
451    *          bean context property setters (e.g. {@link RestClientBuilder#swaps(Object...)}), or generic property setters (e.g. {@link RestClientBuilder#set(String, Object)}) defined on this builder class.
452    *    </ul>
453    * <p>
454    *    {@link UonParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
455    *    <ul>
456    *       <li>The parser can be configured using any of the parser property setters (e.g. {@link RestClientBuilder#strict()}),
457    *          bean context property setters (e.g. {@link RestClientBuilder#swaps(Object...)}), or generic property setters (e.g. {@link RestClientBuilder#set(String, Object)}) defined on this builder class.
458    *    </ul>
459    * <p>
460    *    <c>Accept</c> request header will be set to <js>"text/uon"</js> unless overridden
461    *       by {@link RestRequest#header(String,Object)} or {@link RestRequest#accept(Object)}.
462    * <p>
463    *    <c>Content-Type</c> request header will be set to <js>"text/uon"</js> unless overridden
464    *       by {@link RestRequest#header(String,Object)} or {@link RestRequest#contentType(Object)}.
465    * <p>
466    *    Identical to calling <c>serializer(UonSerializer.<jk>class</jk>).parser(UonParser.<jk>class</jk>)</c>.
467    *
468    * <h5 class='section'>Example:</h5>
469    * <p class='bcode w800'>
470    *    <jc>// Construct a client that uses UON marshalling.</jc>
471    *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().uon().build();
472    * </p>
473    *
474    * @return This object (for method chaining).
475    */
476   public RestRequest uon() {
477      return serializer(UonSerializer.class).parser(UonParser.class);
478   }
479
480   /**
481    * Convenience method for specifying URL-Encoding as the marshalling transmission media type for this request only.
482    *
483    * <p>
484    *    {@link UrlEncodingSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
485    *    <ul>
486    *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link RestClientBuilder#sortCollections()}),
487    *          bean context property setters (e.g. {@link RestClientBuilder#swaps(Object...)}), or generic property setters (e.g. {@link RestClientBuilder#set(String, Object)}) defined on this builder class.
488    *       <li>This serializer is NOT used when using the {@link RestRequest#formData(String, Object)} (and related) methods for constructing
489    *          the request body.  Instead, the part serializer specified via {@link RestClientBuilder#partSerializer(Class)} is used.
490    *    </ul>
491    * <p>
492    *    {@link UrlEncodingParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
493    *    <ul>
494    *       <li>The parser can be configured using any of the parser property setters (e.g. {@link RestClientBuilder#strict()}),
495    *          bean context property setters (e.g. {@link RestClientBuilder#swaps(Object...)}), or generic property setters (e.g. {@link RestClientBuilder#set(String, Object)}) defined on this builder class.
496    *    </ul>
497    * <p>
498    *    <c>Accept</c> request header will be set to <js>"application/x-www-form-urlencoded"</js> unless overridden
499    *       by {@link RestRequest#header(String,Object)} or {@link RestRequest#accept(Object)}.
500    * <p>
501    *    <c>Content-Type</c> request header will be set to <js>"application/x-www-form-urlencoded"</js> unless overridden
502    *       by {@link RestRequest#header(String,Object)} or {@link RestRequest#contentType(Object)}.
503    * <p>
504    *    Identical to calling <c>serializer(UrlEncodingSerializer.<jk>class</jk>).parser(UrlEncodingParser.<jk>class</jk>)</c>.
505    *
506    * <h5 class='section'>Example:</h5>
507    * <p class='bcode w800'>
508    *    <jc>// Construct a client that uses URL-Encoded marshalling.</jc>
509    *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().urlEnc().build();
510    * </p>
511    *
512    * @return This object (for method chaining).
513    */
514   public RestRequest urlEnc() {
515      return serializer(UrlEncodingSerializer.class).parser(UrlEncodingParser.class);
516   }
517
518   /**
519    * Convenience method for specifying OpenAPI as the marshalling transmission media type for this request only.
520    *
521    * <p>
522    * OpenAPI is a language that allows serialization to formats that use {@link HttpPartSchema} objects to describe their structure.
523    *
524    * <p>
525    *    {@link OpenApiSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
526    *    <ul>
527    *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link RestClientBuilder#sortCollections()}),
528    *          bean context property setters (e.g. {@link RestClientBuilder#swaps(Object...)}), or generic property setters (e.g. {@link RestClientBuilder#set(String, Object)}) defined on this builder class.
529    *       <li>Typically the {@link RestRequest#body(Object, HttpPartSchema)} method will be used to specify the body of the request with the
530    *          schema describing it's structure.
531    *    </ul>
532    * <p>
533    *    {@link OpenApiParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
534    *    <ul>
535    *       <li>The parser can be configured using any of the parser property setters (e.g. {@link RestClientBuilder#strict()}),
536    *          bean context property setters (e.g. {@link RestClientBuilder#swaps(Object...)}), or generic property setters (e.g. {@link RestClientBuilder#set(String, Object)}) defined on this builder class.
537    *       <li>Typically the {@link RestResponseBody#schema(HttpPartSchema)} method will be used to specify the structure of the response body.
538    *    </ul>
539    * <p>
540    *    <c>Accept</c> request header will be set to <js>"text/openapi"</js> unless overridden
541    *       by {@link RestRequest#header(String,Object)} or {@link RestRequest#accept(Object)}.
542    * <p>
543    *    <c>Content-Type</c> request header will be set to <js>"text/openapi"</js> unless overridden
544    *       by {@link RestRequest#header(String,Object)} or {@link RestRequest#contentType(Object)}.
545    * <p>
546    *    Identical to calling <c>serializer(OpenApiSerializer.<jk>class</jk>).parser(OpenApiParser.<jk>class</jk>)</c>.
547    *
548    * <h5 class='section'>Example:</h5>
549    * <p class='bcode w800'>
550    *    <jc>// Construct a client that uses OpenAPI marshalling.</jc>
551    *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().openApi().build();
552    * </p>
553    *
554    * @return This object (for method chaining).
555    */
556   public RestRequest openApi() {
557      return serializer(OpenApiSerializer.class).parser(OpenApiParser.class);
558   }
559
560   /**
561    * Specifies the serializer to use on the request body.
562    *
563    * <p>
564    * Overrides the serializers specified on the {@link RestClient}.
565    *
566    * <p>
567    *    The serializer is not modified by an of the serializer property setters (e.g. {@link RestClientBuilder#sortCollections()}),
568    *    bean context property setters (e.g. {@link RestClientBuilder#swaps(Object...)}), or generic property setters (e.g. {@link RestClientBuilder#set(String, Object)}) defined on this builder class.
569    *
570    * <p>
571    * If the <c>Content-Type</c> header is not set on the request, it will be set to the media type of this serializer.
572    *
573    * @param serializer The serializer used to serialize POJOs to the body of the HTTP request.
574    * @return This object (for method chaining).
575    */
576   public RestRequest serializer(Serializer serializer) {
577      this.serializer = serializer;
578      return this;
579   }
580
581   /**
582    * Specifies the serializer to use on the request body.
583    *
584    * <p>
585    * Overrides the serializers specified on the {@link RestClient}.
586    *
587    * <p>
588    *    The serializer can be configured using any of the serializer property setters (e.g. {@link RestClientBuilder#sortCollections()}),
589    *    bean context property setters (e.g. {@link RestClientBuilder#swaps(Object...)}), or generic property setters (e.g. {@link RestClientBuilder#set(String, Object)}) defined on this builder class.
590    *
591    * <p>
592    * If the <c>Content-Type</c> header is not set on the request, it will be set to the media type of this serializer.
593    *
594    * @param serializer The serializer used to serialize POJOs to the body of the HTTP request.
595    * @return This object (for method chaining).
596    */
597   public RestRequest serializer(Class<? extends Serializer> serializer) {
598      this.serializer = client.getInstance(serializer);
599      return this;
600   }
601
602   /**
603    * Specifies the parser to use on the response body.
604    *
605    * <p>
606    * Overrides the parsers specified on the {@link RestClient}.
607    *
608    * <p>
609    *    The parser is not modified by any of the parser property setters (e.g. {@link RestClientBuilder#strict()}),
610    *    bean context property setters (e.g. {@link RestClientBuilder#swaps(Object...)}), or generic property setters (e.g. {@link RestClientBuilder#set(String, Object)}) defined on this builder class.
611    *
612    * <p>
613    * If the <c>Accept</c> header is not set on the request, it will be set to the media type of this parser.
614    *
615    * @param parser The parser used to parse POJOs from the body of the HTTP response.
616    * @return This object (for method chaining).
617    */
618   public RestRequest parser(Parser parser) {
619      this.parser = parser;
620      return this;
621   }
622
623   /**
624    * Specifies the parser to use on the response body.
625    *
626    * <p>
627    * Overrides the parsers specified on the {@link RestClient}.
628    *
629    * <p>
630    *    The parser can be configured using any of the parser property setters (e.g. {@link RestClientBuilder#strict()}),
631    *    bean context property setters (e.g. {@link RestClientBuilder#swaps(Object...)}), or generic property setters (e.g. {@link RestClientBuilder#set(String, Object)}) defined on this builder class.
632    *
633    * <p>
634    * If the <c>Accept</c> header is not set on the request, it will be set to the media type of this parser.
635    *
636    * @param parser The parser used to parse POJOs from the body of the HTTP response.
637    * @return This object (for method chaining).
638    */
639   public RestRequest parser(Class<? extends Parser> parser) {
640      this.parser = client.getInstance(parser);
641      return this;
642   }
643
644   /**
645    * Allows you to override what status codes are considered error codes that would result in a {@link RestCallException}.
646    *
647    * <p>
648    * The default error code predicate is: <code>x -&gt; x &gt;= 400</code>.
649    *
650    * @param value The new predicate for calculating error codes.
651    * @return This object (for method chaining).
652    */
653   public RestRequest errorCodes(Predicate<Integer> value) {
654      this.errorCodes = value;
655      return this;
656   }
657
658   /**
659    * Add one or more interceptors for this call only.
660    *
661    * @param interceptors The interceptors to add to this call.
662    * @return This object (for method chaining).
663    * @throws RestCallException If init method on interceptor threw an exception.
664    */
665   public RestRequest interceptors(RestCallInterceptor...interceptors) throws RestCallException {
666      try {
667         for (RestCallInterceptor i : interceptors) {
668            this.interceptors.add(i);
669            i.onInit(this);
670         }
671      } catch (RuntimeException | RestCallException e) {
672         throw e;
673      } catch (Exception e) {
674         throw new RestCallException(null, e, "Interceptor threw an exception on init.");
675      }
676
677      return this;
678   }
679
680   /**
681    * Prevent {@link RestCallException RestCallExceptions} from being thrown when HTTP status 400+ is encountered.
682    *
683    * <p>
684    * This overrides the <l>ignoreErrors</l> property on the client.
685    *
686    * @return This object (for method chaining).
687    */
688   public RestRequest ignoreErrors() {
689      this.ignoreErrors = true;
690      return this;
691   }
692
693   /**
694    * Sets <c>Debug: value</c> header on this request.
695    *
696    * @return This object (for method chaining).
697    * @throws RestCallException Invalid input.
698    */
699   public RestRequest debug() throws RestCallException {
700      header("Debug", true);
701      return this;
702   }
703
704   /**
705    * Returns <jk>true</jk> if debug mode is currently enabled.
706    */
707   @Override
708   public boolean isDebug() {
709      return getHeader("Debug", "false").equalsIgnoreCase("true");
710   }
711
712   /**
713    * Specifies the target host for the request.
714    *
715    * @param target The target host for the request.
716    *    Implementations may accept <jk>null</jk> if they can still determine a route, for example to a default
717    *    target or by inspecting the request.
718    * @return This object (for method chaining).
719    */
720   public RestRequest target(HttpHost target) {
721      this.target = target;
722      return this;
723   }
724
725   /**
726    * Override the context to use for the execution.
727    *
728    * @param context The context to use for the execution, or <jk>null</jk> to use the default context.
729    * @return This object (for method chaining).
730    */
731   public RestRequest context(HttpContext context) {
732      this.context = context;
733      return this;
734   }
735
736   //------------------------------------------------------------------------------------------------------------------
737   // URI
738   //------------------------------------------------------------------------------------------------------------------
739
740   /**
741    * Sets the URI for this request.
742    *
743    * <p>
744    * Can be any of the following types:
745    * <ul>
746    *    <li>{@link URI}
747    *    <li>{@link URL}
748    *    <li>{@link URIBuilder}
749    *    <li>Anything else converted to a string using {@link Object#toString()}.
750    * </ul>
751    *
752    * <p>
753    * Relative URI strings will be interpreted as relative to the root URI defined on the client.
754    *
755    * @param uri
756    *    The URI of the remote REST resource.
757    *    <br>This overrides the URI passed in from the client.
758    *    <br>Can be any of the following types:
759    *    <ul>
760    *       <li>{@link URIBuilder}
761    *       <li>{@link URI}
762    *       <li>{@link URL}
763    *       <li>{@link String}
764    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
765    *    </ul>
766    * @return This object (for method chaining).
767    * @throws RestCallException Invalid URI syntax detected.
768    */
769   public RestRequest uri(Object uri) throws RestCallException {
770      URI x = client.toURI(uri, null);
771      if (x.getScheme() != null)
772         uriBuilder.setScheme(x.getScheme());
773      if (x.getHost() != null)
774         uriBuilder.setHost(x.getHost());
775      if (x.getPort() != -1)
776         uriBuilder.setPort(x.getPort());
777      if (x.getUserInfo() != null)
778         uriBuilder.setUserInfo(x.getUserInfo());
779      if (x.getFragment() != null)
780         uriBuilder.setFragment(x.getFragment());
781      if (x.getQuery() != null)
782         uriBuilder.setCustomQuery(x.getQuery());
783      uriBuilder.setPath(x.getPath());
784      return this;
785   }
786
787   /**
788    * Sets the URI scheme.
789    *
790    * @param scheme The new URI host.
791    * @return This object (for method chaining).
792    */
793   public RestRequest scheme(String scheme) {
794      uriBuilder.setScheme(scheme);
795      return this;
796   }
797
798   /**
799    * Sets the URI host.
800    *
801    * @param host The new URI host.
802    * @return This object (for method chaining).
803    */
804   public RestRequest host(String host) {
805      uriBuilder.setHost(host);
806      return this;
807   }
808
809   /**
810    * Sets the URI port.
811    *
812    * @param port The new URI port.
813    * @return This object (for method chaining).
814    */
815   public RestRequest port(int port) {
816      uriBuilder.setPort(port);
817      return this;
818   }
819
820   /**
821    * Sets the URI user info.
822    *
823    * @param userInfo The new URI user info.
824    * @return This object (for method chaining).
825    */
826   public RestRequest userInfo(String userInfo) {
827      uriBuilder.setUserInfo(userInfo);
828      return this;
829   }
830
831   /**
832    * Sets the URI user info.
833    *
834    * @param username The new URI username.
835    * @param password The new URI password.
836    * @return This object (for method chaining).
837    */
838   public RestRequest userInfo(String username, String password) {
839      uriBuilder.setUserInfo(username, password);
840      return this;
841   }
842
843   /**
844    * Sets the URI fragment.
845    *
846    * @param fragment The URI fragment.  The value is expected to be unescaped and may contain non ASCII characters.
847    * @return This object (for method chaining).
848    */
849   public RestRequest fragment(String fragment) {
850      uriBuilder.setFragment(fragment);
851      return this;
852   }
853
854   //------------------------------------------------------------------------------------------------------------------
855   // Path
856   //------------------------------------------------------------------------------------------------------------------
857
858   /**
859    * Replaces a path parameter of the form <js>"{name}"</js> in the URI.
860    *
861    * <h5 class='section'>Example:</h5>
862    * <p class='bcode w800'>
863    *    <jc>// Sets path to "/bar".</jc>
864    *    <jv>client</jv>
865    *       .get(<js>"/{foo}"</js>)
866    *       .path(<js>"foo"</js>, <js>"bar"</js>)
867    *       .run();
868    * </p>
869    *
870    * @param name The parameter name.
871    * @param value The parameter value.
872    *    <ul>
873    *       <li>Value can be any POJO or POJO {@link Supplier}.
874    *       <li>Value converted to a string using the configured part serializer.
875    *    </ul>
876    * @return This object (for method chaining).
877    * @throws RestCallException Invalid input.
878    */
879   public RestRequest path(String name, Object value) throws RestCallException {
880      return paths(serializedNameValuePair(name, value, PATH, partSerializer, null, null));
881   }
882
883   /**
884    * Replaces a path parameter of the form <js>"{name}"</js> in the URI.
885    *
886    * <h5 class='section'>Example:</h5>
887    * <p class='bcode w800'>
888    *    <jc>// Sets path to "/bar".</jc>
889    *    <jv>client</jv>
890    *       .get(<js>"/{foo}"</js>)
891    *       .path(BasicNameValuePair.<jsm>of</jsm>(<js>"foo"</js>, <js>"bar"</js>))
892    *       .run();
893    * </p>
894    *
895    * @param pair The parameter.
896    * @return This object (for method chaining).
897    * @throws RestCallException Invalid input.
898    */
899   public RestRequest path(NameValuePair pair) throws RestCallException {
900      return paths(pair);
901   }
902
903   /**
904    * Replaces a path parameter of the form <js>"{name}"</js> in the URI.
905    *
906    * <h5 class='section'>Example:</h5>
907    * <p class='bcode w800'>
908    *    <jc>// Sets path to "/bar|baz".</jc>
909    *    <jv>client</jv>
910    *       .get(<js>"/{foo}"</js>)
911    *       .path(
912    *          <js>"foo"</js>, AList.<jsm>of</jsm>(<js>"bar"</js>,<js>"baz"</js>),
913    *          HttpPartSchema.<jsf>T_ARRAY_PIPES</jsf>
914    *       )
915    *       .run();
916    * </p>
917    *
918    * @param name The parameter name.
919    * @param value The parameter value.
920    *    <ul>
921    *       <li>Value can be any POJO or POJO {@link Supplier}.
922    *       <li>Value converted to a string using the configured part serializer.
923    *    </ul>
924    * @param schema The part schema.  Can be <jk>null</jk>.
925    * @return This object (for method chaining).
926    * @throws RestCallException Invalid input.
927    */
928   public RestRequest path(String name, Object value, HttpPartSchema schema) throws RestCallException {
929      return paths(serializedNameValuePair(name, value, PATH, partSerializer, schema, null));
930   }
931
932   /**
933    * Replaces multiple path parameter of the form <js>"{name}"</js> in the URI.
934    *
935    * <h5 class='section'>Example:</h5>
936    * <p class='bcode w800'>
937    *    <jc>// Sets path to "/baz/qux".</jc>
938    *    <jv>client</jv>
939    *       .get(<js>"/{foo}/{bar}"</js>)
940    *       .paths(
941    *          BasicNameValuePair.<jsm>of</jsm>(<js>"foo"</js>, <js>"baz"</js>),
942    *          AMap.<jsm>of</jsm>(<js>"bar"</js>, <js>"qux"</js>)
943    *       )
944    *       .run();
945    * </p>
946    *
947    * @param params
948    *    The path parameters to set.
949    *    <br>Can be any of the following types:
950    *    <ul>
951    *       <li>{@link NameValuePair}
952    *       <li>{@link NameValuePairable}
953    *       <li>{@link java.util.Map.Entry}
954    *       <li>{@link NameValuePairSupplier}
955    *       <li>{@link Map}
956    *       <ul>
957    *          <li>Values can be any POJO.
958    *          <li>Values converted to a string using the configured part serializer.
959    *       </ul>
960    *       <li>A collection or array of anything on this list.
961    * </ul>
962    * @return This object (for method chaining).
963    * @throws RestCallException Invalid input.
964    */
965   @SuppressWarnings("rawtypes")
966   public RestRequest paths(Object...params) throws RestCallException {
967      for (Object o : params) {
968         if (BasicNameValuePair.canCast(o)) {
969            innerPath(BasicNameValuePair.cast(o));
970         } else if (o instanceof NameValuePairSupplier) {
971            for (NameValuePair p : (NameValuePairSupplier)o)
972               innerPath(p);
973         } else if (o instanceof Collection) {
974            for (Object o2 : (Collection<?>)o)
975               innerPath(BasicNameValuePair.cast(o2));
976         } else if (o != null && o.getClass().isArray()) {
977            for (int i = 0; i < Array.getLength(o); i++)
978               innerPath(BasicNameValuePair.cast(Array.get(o, i)));
979         } else if (o instanceof Map) {
980            for (Map.Entry e : toMap(o).entrySet())
981               innerPath(serializedNameValuePair(e.getKey(), e.getValue(), PATH, partSerializer, null, null));
982         } else if (isBean(o)) {
983            for (Map.Entry<String,Object> e : toBeanMap(o).entrySet())
984               innerPath(serializedNameValuePair(e.getKey(), e.getValue(), PATH, partSerializer, null, null));
985         } else if (o != null) {
986            throw new RestCallException(null, null, "Invalid type passed to paths(): {0}", className(o));
987         }
988      }
989      return this;
990   }
991
992   /**
993    * Replaces path parameters of the form <js>"{name}"</js> in the URI using free-form key/value pairs.
994    *
995    * <h5 class='section'>Example:</h5>
996    * <p class='bcode w800'>
997    *    <jc>// Sets path to "/baz/qux".</jc>
998    *    <jv>client</jv>
999    *       .get(<js>"/{foo}/{bar}"</js>)
1000    *       .pathPairs(
1001    *          <js>"foo"</js>,<js>"baz"</js>,
1002    *          <js>"bar"</js>,<js>"qux"</js>
1003    *       )
1004    *       .run();
1005    * </p>
1006    *
1007    * @param pairs The path key/value pairs.
1008    *    <ul>
1009    *       <li>Values can be any POJO.
1010    *       <li>Values converted to a string using the configured part serializer.
1011    *    </ul>
1012    * @return This object (for method chaining).
1013    * @throws RestCallException Invalid input.
1014    */
1015   public RestRequest pathPairs(Object...pairs) throws RestCallException {
1016      if (pairs.length % 2 != 0)
1017         throw new RestCallException(null, null, "Odd number of parameters passed into pathPairs()");
1018      for (int i = 0; i < pairs.length; i+=2)
1019         paths(serializedNameValuePair(pairs[i], pairs[i+1], PATH, partSerializer, null, null));
1020      return this;
1021   }
1022
1023   RestRequest pathArg(String name, Object value, HttpPartSchema schema, HttpPartSerializerSession serializer) throws RestCallException {
1024      boolean isMulti = isEmpty(name) || "*".equals(name) || value instanceof NameValuePairSupplier || isNameValuePairArray(value);
1025
1026      if (! isMulti)
1027         return innerPath(serializedNameValuePair(name, value, PATH, serializer, schema, null));
1028
1029      if (BasicNameValuePair.canCast(value)) {
1030         innerPath(BasicNameValuePair.cast(value));
1031      } else if (value instanceof NameValuePairSupplier) {
1032         for (Object o : (NameValuePairSupplier)value)
1033            innerPath(BasicNameValuePair.cast(o));
1034      } else if (value instanceof Collection) {
1035         for (Object o : (Collection<?>)value)
1036            innerPath(BasicNameValuePair.cast(o));
1037      } else if (value != null && value.getClass().isArray()) {
1038         for (int i = 0; i < Array.getLength(value); i++)
1039            innerPath(BasicNameValuePair.cast(Array.get(value, i)));
1040      } else if (value instanceof Map) {
1041         for (Map.Entry<Object,Object> p : toMap(value).entrySet())
1042            innerPath(serializedNameValuePair(p.getKey(), p.getValue(), PATH, serializer, schema, null));
1043      } else if (isBean(value)) {
1044         for (Map.Entry<String,Object> p : toBeanMap(value).entrySet())
1045            innerPath(serializedNameValuePair(p.getKey(), p.getValue(), PATH, serializer, schema, null));
1046      } else if (value != null) {
1047         throw new RestCallException(null, null, "Invalid value type for path arg ''{0}'': {1}", name, className(value));
1048      }
1049      return this;
1050   }
1051
1052   private RestRequest innerPath(NameValuePair param) throws RestCallException {
1053      String path = uriBuilder.getPath();
1054      String name = param.getName(), value = param.getValue();
1055      String var = "{" + name + "}";
1056      if (path.indexOf(var) == -1 && ! name.equals("/*"))
1057         throw new RestCallException(null, null, "Path variable {"+name+"} was not found in path.");
1058      String p = null;
1059      if (name.equals("/*"))
1060         p = path.replaceAll("\\/\\*$", "/" + value);
1061      else
1062         p = path.replace(var, String.valueOf(value));
1063      uriBuilder.setPath(p);
1064      return this;
1065   }
1066
1067   //------------------------------------------------------------------------------------------------------------------
1068   // Query
1069   //------------------------------------------------------------------------------------------------------------------
1070
1071   /**
1072    * Sets a query parameter on the URI.
1073    *
1074    * <h5 class='section'>Example:</h5>
1075    * <p class='bcode w800'>
1076    *    <jc>// Adds query parameter "foo=bar|baz".</jc>
1077    *    <jv>client</jv>
1078    *       .get(<jsf>URI</jsf>)
1079    *       .query(
1080    *          <jsf>APPEND</jsf>,
1081    *          <js>"foo"</js>, AList.<jsm>of</jsm>(<js>"bar"</js>,<js>"baz"</js>),
1082    *          HttpPartSchema.<jsf>T_ARRAY_PIPES</jsf>
1083    *    )
1084    *       .run();
1085    * </p>
1086    *
1087    * @param flag How to add this parameter.
1088    *    <ul>
1089    *       <li>{@link AddFlag#APPEND APPEND} (default) - Append to end.
1090    *       <li>{@link AddFlag#PREPEND PREPEND} - Prepend to beginning.
1091    *       <li>{@link AddFlag#REPLACE REPLACE} - Delete any existing with same name and append to end.
1092    *    </ul>
1093    * @param name The parameter name.
1094    * @param value The parameter value.
1095    *    <ul>
1096    *       <li>Value can be any POJO or POJO {@link Supplier}.
1097    *       <li>Value converted to a string using the configured part serializer.
1098    *    </ul>
1099    * @param schema The schema object that defines the format of the output.
1100    *    <ul>
1101    *       <li>If <jk>null</jk>, defaults to {@link HttpPartSchema#DEFAULT}.
1102    *       <li>Only used if serializer is schema-aware (e.g. {@link OpenApiSerializer}).
1103    *    </ul>
1104    * @return This object (for method chaining).
1105    * @throws RestCallException Invalid input.
1106    */
1107   public RestRequest query(AddFlag flag, String name, Object value, HttpPartSchema schema) throws RestCallException {
1108      return queries(flag, serializedNameValuePair(name, value, QUERY, partSerializer, schema, EnumSet.of(flag)));
1109   }
1110
1111   /**
1112    * Adds a query parameter to the URI.
1113    *
1114    * <h5 class='section'>Example:</h5>
1115    * <p class='bcode w800'>
1116    *    <jc>// Adds query parameter "foo=bar".</jc>
1117    *    <jv>client</jv>
1118    *       .get(<jsf>URI</jsf>)
1119    *       .query(<js>"foo"</js>, <js>"bar"</js>)
1120    *       .run();
1121    * </p>
1122    *
1123    * @param name The parameter name.
1124    * @param value The parameter value.
1125    *    <ul>
1126    *       <li>Value can be any POJO or POJO {@link Supplier}.
1127    *       <li>Value converted to a string using the configured part serializer.
1128    *    </ul>
1129    * @return This object (for method chaining).
1130    * @throws RestCallException Invalid input.
1131    */
1132   public RestRequest query(String name, Object value) throws RestCallException {
1133      return queries(serializedNameValuePair(name, value, QUERY, partSerializer, null, null));
1134   }
1135
1136   /**
1137    * Adds a query parameter to the URI.
1138    *
1139    * <h5 class='section'>Example:</h5>
1140    * <p class='bcode w800'>
1141    *    <jc>// Adds query parameter "foo=bar".</jc>
1142    *    <jv>client</jv>
1143    *       .get(<jsf>URI</jsf>)
1144    *       .query(BasicNameValuePair.<jsm>of</jsm>(<js>"foo"</js>, <js>"bar"</js>))
1145    *       .run();
1146    * </p>
1147    *
1148    * @param pair The parameter.
1149    * @return This object (for method chaining).
1150    * @throws RestCallException Invalid input.
1151    */
1152   public RestRequest query(NameValuePair pair) throws RestCallException {
1153      return queries(pair);
1154   }
1155
1156   /**
1157    * Adds a query parameter to the URI.
1158    *
1159    * <p>
1160    * The optional schema allows for specifying how part should be serialized (as a pipe-delimited list for example).
1161    *
1162    * <h5 class='section'>Example:</h5>
1163    * <p class='bcode w800'>
1164    *    <jc>// Creates query parameter "foo=bar|baz"</jc>
1165    *    <jv>client</jv>
1166    *       .get(<jsf>URI</jsf>)
1167    *       .query(
1168    *          <js>"foo"</js>, AList.<jsm>of</jsm>(<js>"bar"</js>,<js>"baz"</js>),
1169    *          HttpPartSchema.<jsf>T_ARRAY_PIPES</jsf>
1170    *       )
1171    *       .run();
1172    * </p>
1173    *
1174    * @param name The parameter name.
1175    * @param value The parameter value.
1176    *    <ul>
1177    *       <li>Value can be any POJO or POJO {@link Supplier}.
1178    *       <li>Value converted to a string using the configured part serializer.
1179    *    </ul>
1180    * @param schema The HTTP part schema.  Can be <jk>null</jk>.
1181    * @return This object (for method chaining).
1182    * @throws RestCallException Invalid input.
1183    */
1184   public RestRequest query(String name, Object value, HttpPartSchema schema) throws RestCallException {
1185      return queries(serializedNameValuePair(name, value, QUERY, partSerializer, schema, null));
1186   }
1187
1188   /**
1189    * Adds a query parameter to the URI.
1190    *
1191    * <h5 class='section'>Example:</h5>
1192    * <p class='bcode w800'>
1193    *    <jc>// Adds query parameter "foo=bar".</jc>
1194    *    <jv>client</jv>
1195    *       .get(<jsf>URI</jsf>)
1196    *       .query(
1197    *          <jsf>APPEND</jsf>,
1198    *          <js>"foo"</js>, <js>"bar"</js>
1199    *    )
1200    *       .run();
1201    * </p>
1202    *
1203    * @param flag How to add this parameter.
1204    *    <ul>
1205    *       <li>{@link AddFlag#APPEND APPEND} (default) - Append to end.
1206    *       <li>{@link AddFlag#PREPEND PREPEND} - Prepend to beginning.
1207    *       <li>{@link AddFlag#REPLACE REPLACE} - Delete any existing with same name and append to end.
1208    *    </ul>
1209    * @param name The parameter name.
1210    * @param value The parameter value.
1211    *    <ul>
1212    *       <li>Value can be any POJO or POJO {@link Supplier}.
1213    *       <li>Value converted to a string using the configured part serializer.
1214    *    </ul>
1215    * @return This object (for method chaining).
1216    * @throws RestCallException Invalid input.
1217    */
1218   public RestRequest query(AddFlag flag, String name, Object value) throws RestCallException {
1219      return queries(flag, serializedNameValuePair(name, value, QUERY, partSerializer, null, EnumSet.of(flag)));
1220   }
1221
1222   /**
1223    * Sets multiple parameters on the query string.
1224    *
1225    * <h5 class='section'>Example:</h5>
1226    * <p class='bcode w800'>
1227    *    <jc>// Adds query parameters "foo=bar&baz=qux".</jc>
1228    *    <jv>client</jv>
1229    *       .get(<jsf>URI</jsf>)
1230    *       .queries(
1231    *          BasicNameValuePair.<jsm>of</jsm>(<js>"foo"</js>,<js>"bar"</js>),
1232    *          AMap.<jsm>of</jsm>(<js>"baz"</js>,<js>"qux"</js>)
1233    *       )
1234    *       .run();
1235    * </p>
1236    *
1237    * @param params
1238    *    The parameters to set.
1239    *    <br>Can be any of the following types:
1240    *    <ul>
1241    *       <li>{@link NameValuePair}
1242    *       <li>{@link NameValuePairable}
1243    *       <li>{@link java.util.Map.Entry}
1244    *       <li>{@link NameValuePairSupplier}
1245    *       <li>{@link Map}
1246    *       <ul>
1247    *          <li>Values can be any POJO.
1248    *          <li>Values converted to a string using the configured part serializer.
1249    *       </ul>
1250    *       <li>A collection or array of anything on this list.
1251    * </ul>
1252    * @return This object (for method chaining).
1253    * @throws RestCallException Invalid input.
1254    */
1255   public RestRequest queries(Object...params) throws RestCallException {
1256      return queries(APPEND, params);
1257   }
1258
1259   /**
1260    * Sets multiple parameters on the query string.
1261    *
1262    * <h5 class='section'>Example:</h5>
1263    * <p class='bcode w800'>
1264    *    <jc>// Adds query parameters "foo=bar&baz=qux".</jc>
1265    *    <jv>client</jv>
1266    *       .get(<jsf>URI</jsf>)
1267    *       .queries(
1268    *          <jsf>APPEND</jsf>,
1269    *          BasicNameValuePair.<jsm>of</jsm>(<js>"foo"</js>,<js>"bar"</js>),
1270    *          AMap.<jsm>of</jsm>(<js>"baz"</js>,<js>"qux"</js>)
1271    *       )
1272    *       .run();
1273    * </p>
1274    *
1275    * @param flag How to add this parameter.
1276    *    <ul>
1277    *       <li>{@link AddFlag#APPEND APPEND} (default) - Append to end.
1278    *       <li>{@link AddFlag#PREPEND PREPEND} - Prepend to beginning.
1279    *       <li>{@link AddFlag#REPLACE REPLACE} - Delete any existing with same name and append to end.
1280    *    </ul>
1281    * @param params
1282    *    The parameters to set.
1283    *    <br>Can be any of the following types:
1284    *    <ul>
1285    *       <li>{@link NameValuePair}
1286    *       <li>{@link NameValuePairable}
1287    *       <li>{@link java.util.Map.Entry}
1288    *       <li>{@link NameValuePairSupplier}
1289    *       <li>{@link Map}
1290    *       <ul>
1291    *          <li>Values can be any POJO.
1292    *          <li>Values converted to a string using the configured part serializer.
1293    *       </ul>
1294    *       <li>A collection or array of anything on this list.
1295    * </ul>
1296    * @return This object (for method chaining).
1297    * @throws RestCallException Invalid input.
1298    */
1299   public RestRequest queries(AddFlag flag, Object...params) throws RestCallException {
1300      List<NameValuePair> l = new ArrayList<>();
1301      for (Object o : params) {
1302         if (BasicNameValuePair.canCast(o)) {
1303            l.add(BasicNameValuePair.cast(o));
1304         } else if (o instanceof NameValuePairSupplier) {
1305            for (NameValuePair p : (NameValuePairSupplier)o)
1306               l.add(p);
1307         } else if (o instanceof Collection) {
1308            for (Object o2 : (Collection<?>)o)
1309               l.add(BasicNameValuePair.cast(o2));
1310         } else if (o != null && o.getClass().isArray()) {
1311            for (int i = 0; i < Array.getLength(o); i++)
1312               l.add(BasicNameValuePair.cast(Array.get(o, i)));
1313         } else if (o instanceof Map) {
1314            for (Map.Entry<Object,Object> e : toMap(o).entrySet())
1315               l.add(serializedNameValuePair(e.getKey(), e.getValue(), QUERY, partSerializer, null, EnumSet.of(flag)));
1316         } else if (isBean(o)) {
1317            for (Map.Entry<String,Object> e : toBeanMap(o).entrySet())
1318               l.add(serializedNameValuePair(e.getKey(), e.getValue(), QUERY, partSerializer, null, EnumSet.of(flag)));
1319         } else if (o != null) {
1320            throw new RestCallException(null, null, "Invalid type passed to queries(): {0}", className(o));
1321         }
1322      }
1323      return innerQuery(EnumSet.of(flag), l);
1324   }
1325
1326   /**
1327    * Adds query parameters to the URI query using free-form key/value pairs..
1328    *
1329    * <h5 class='section'>Example:</h5>
1330    * <p class='bcode w800'>
1331    *    <jc>// Adds query parameters "foo=bar&baz=qux".</jc>
1332    *    <jv>client</jv>
1333    *       .get(<jsf>URI</jsf>)
1334    *       .queryPairs(<js>"foo"</js>,<js>"bar"</js>,<js>"baz"</js>,<js>"qux"</js>)
1335    *       .run();
1336    * </p>
1337    *
1338    * @param pairs The query key/value pairs.
1339    *    <ul>
1340    *       <li>Values can be any POJO.
1341    *       <li>Values converted to a string using the configured part serializer.
1342    *    </ul>
1343    * @return This object (for method chaining).
1344    * @throws RestCallException Invalid input.
1345    */
1346   public RestRequest queryPairs(Object...pairs) throws RestCallException {
1347      if (pairs.length % 2 != 0)
1348         throw new RestCallException(null, null, "Odd number of parameters passed into queryPairs()");
1349      for (int i = 0; i < pairs.length; i+=2)
1350         queries(serializedNameValuePair(pairs[i], pairs[i+1], QUERY, partSerializer, null, null));
1351      return this;
1352   }
1353
1354   /**
1355    * Adds a free-form custom query.
1356    *
1357    * <h5 class='section'>Example:</h5>
1358    * <p class='bcode w800'>
1359    *    <jc>// Adds query parameter "foo=bar&baz=qux".</jc>
1360    *    <jv>client</jv>
1361    *       .get(<jsf>URI</jsf>)
1362    *       .queryCustom(<js>"foo=bar&baz=qux"</js>)
1363    *       .run();
1364    * </p>
1365    *
1366    * @param value The parameter value.
1367    *    <br>Can be any of the following types:
1368    *    <ul>
1369    *       <li>
1370    *          {@link CharSequence}
1371    *       <li>
1372    *          {@link Reader} - Raw contents of {@code Reader} will be serialized to remote resource.
1373    *       <li>
1374    *          {@link InputStream} - Raw contents of {@code InputStream} will be serialized to remote resource.
1375    *       <li>
1376    *          {@link NameValuePairSupplier} - Converted to a URL-encoded query.
1377    *    </ul>
1378    * @return This object (for method chaining).
1379    * @throws RestCallException Invalid input.
1380    */
1381   public RestRequest queryCustom(Object value) throws RestCallException {
1382      try {
1383         String q = null;
1384         if (value instanceof Reader)
1385            q = IOUtils.read((Reader)value);
1386         else if (value instanceof InputStream)
1387            q = IOUtils.read((InputStream)value);
1388         else
1389            q = stringify(value);  // Works for NameValuePairs.
1390         uriBuilder.setCustomQuery(q);
1391      } catch (IOException e) {
1392         throw new RestCallException(null, e, "Could not read custom query.");
1393      }
1394      return this;
1395   }
1396
1397   RestRequest queryArg(EnumSet<AddFlag> flags, String name, Object value, HttpPartSchema schema, HttpPartSerializerSession serializer) throws RestCallException {
1398      flags = AddFlag.orDefault(flags);
1399      boolean isMulti = isEmpty(name) || "*".equals(name) || value instanceof NameValuePairSupplier || isNameValuePairArray(value);
1400
1401      if (! isMulti)
1402         return innerQuery(flags, AList.of(serializedNameValuePair(name, value, QUERY, serializer, schema, flags)));
1403
1404      List<NameValuePair> l = AList.of();
1405
1406      if (BasicNameValuePair.canCast(value)) {
1407         l.add(BasicNameValuePair.cast(value));
1408      } else if (value instanceof NameValuePairSupplier) {
1409         for (Object o : (NameValuePairSupplier)value)
1410            l.add(BasicNameValuePair.cast(o));
1411      } else if (value instanceof Collection) {
1412         for (Object o : (Collection<?>)value)
1413            l.add(BasicNameValuePair.cast(o));
1414      } else if (value != null && value.getClass().isArray()) {
1415         for (int i = 0; i < Array.getLength(value); i++)
1416            l.add(BasicNameValuePair.cast(Array.get(value, i)));
1417      } else if (value instanceof Map) {
1418         for (Map.Entry<Object,Object> e : toMap(value).entrySet())
1419            l.add(serializedNameValuePair(e.getKey(), e.getValue(), QUERY, serializer, schema, flags));
1420      } else if (isBean(value)) {
1421         for (Map.Entry<String,Object> e : toBeanMap(value).entrySet())
1422            l.add(serializedNameValuePair(e.getKey(), e.getValue(), QUERY, serializer, schema, flags));
1423      } else {
1424         return queryCustom(value);
1425      }
1426
1427      return innerQuery(flags, l);
1428   }
1429
1430   private RestRequest innerQuery(EnumSet<AddFlag> flags, List<NameValuePair> params) {
1431      flags = AddFlag.orDefault(flags);
1432      params.removeIf(x -> x.getValue() == null);
1433      if (flags.contains(SKIP_IF_EMPTY))
1434         params.removeIf(x -> isEmpty(x.getValue()));
1435      if (flags.contains(REPLACE)) {
1436         List<NameValuePair> l = uriBuilder.getQueryParams();
1437         for (NameValuePair p : params)
1438            for (Iterator<NameValuePair> i = l.iterator(); i.hasNext();)
1439               if (i.next().getName().equals(p.getName()))
1440                  i.remove();
1441         l.addAll(params);
1442         uriBuilder.setParameters(l);
1443      } else if (flags.contains(PREPEND)) {
1444         List<NameValuePair> l = uriBuilder.getQueryParams();
1445         l.addAll(0, params);
1446         uriBuilder.setParameters(l);
1447      } else {
1448         uriBuilder.addParameters(params);
1449      }
1450      return this;
1451   }
1452
1453   //------------------------------------------------------------------------------------------------------------------
1454   // Form data
1455   //------------------------------------------------------------------------------------------------------------------
1456
1457   /**
1458    * Adds a form-data parameter to the request body.
1459    *
1460    * <h5 class='section'>Example:</h5>
1461    * <p class='bcode w800'>
1462    *    <jc>// Adds form data parameter "foo=bar|baz".</jc>
1463    *    <jv>client</jv>
1464    *       .formPost(<jsf>URI</jsf>)
1465    *       .formData(
1466    *          <jsf>APPEND</jsf>,
1467    *          <js>"foo"</js>, AList.<jsm>of</jsm>(<js>"bar"</js>,<js>"baz"</js>),
1468    *          HttpPartSchema.<jsf>T_ARRAY_PIPES</jsf>
1469    *       .run();
1470    * </p>
1471    *
1472    * @param flag How to add this parameter.
1473    *    <ul>
1474    *       <li>{@link AddFlag#APPEND APPEND} (default) - Append to end.
1475    *       <li>{@link AddFlag#PREPEND PREPEND} - Prepend to beginning.
1476    *       <li>{@link AddFlag#REPLACE REPLACE} - Delete any existing with same name and append to end.
1477    *    </ul>
1478    * @param name The parameter name.
1479    * @param value The parameter value.
1480    *    <ul>
1481    *       <li>Value can be any POJO or POJO {@link Supplier}.
1482    *       <li>Value converted to a string using the configured part serializer.
1483    *    </ul>
1484    * @param schema The schema object that defines the format of the output.
1485    *    <ul>
1486    *       <li>If <jk>null</jk>, defaults to {@link HttpPartSchema#DEFAULT}.
1487    *       <li>Only used if serializer is schema-aware (e.g. {@link OpenApiSerializer}).
1488    *    </ul>
1489    * @return This object (for method chaining).
1490    * @throws RestCallException Invalid input.
1491    */
1492   public RestRequest formData(AddFlag flag, String name, Object value, HttpPartSchema schema) throws RestCallException {
1493      return formDatas(flag, serializedNameValuePair(name, value, FORMDATA, partSerializer, schema, EnumSet.of(flag)));
1494   }
1495
1496   /**
1497    * Adds a form-data parameter to the request body.
1498    *
1499    * <h5 class='section'>Example:</h5>
1500    * <p class='bcode w800'>
1501    *    <jc>// Adds form data parameter "foo=bar|baz".</jc>
1502    *    <jv>client</jv>
1503    *       .formPost(<jsf>URI</jsf>)
1504    *       .formData(<js>"foo"</js>, <js>"bar"</js>)
1505    *       .run();
1506    * </p>
1507    *
1508    * @param name The parameter name.
1509    * @param value The parameter value.
1510    *    <ul>
1511    *       <li>Value can be any POJO or POJO {@link Supplier}.
1512    *       <li>Value converted to a string using the configured part serializer.
1513    *    </ul>
1514    * @return This object (for method chaining).
1515    * @throws RestCallException Invalid input.
1516    */
1517   public RestRequest formData(String name, Object value) throws RestCallException {
1518      return formDatas(serializedNameValuePair(name, value, FORMDATA, partSerializer, null, null));
1519   }
1520
1521   /**
1522    * Adds a form-data parameter to the request body.
1523    *
1524    * <h5 class='section'>Example:</h5>
1525    * <p class='bcode w800'>
1526    *    <jc>// Adds form data parameter "foo=bar".</jc>
1527    *    <jv>client</jv>
1528    *       .formPost(<jsf>URI</jsf>)
1529    *       .formData(BasicNameValuePair.<jsm>of</jsm>(<js>"foo"</js>, <js>"bar"</js>))
1530    *       .run();
1531    * </p>
1532    *
1533    * @param pair The parameter.
1534    * @return This object (for method chaining).
1535    * @throws RestCallException Invalid input.
1536    */
1537   public RestRequest formData(NameValuePair pair) throws RestCallException {
1538      return formDatas(pair);
1539   }
1540
1541   /**
1542    * Adds a form-data parameter to the request body.
1543    *
1544    * <p>
1545    * The optional schema allows for specifying how part should be serialized (as a pipe-delimited list for example).
1546    *
1547    * <h5 class='section'>Example:</h5>
1548    * <p class='bcode w800'>
1549    *    <jc>// Adds form data parameter "foo=bar|baz".</jc>
1550    *    <jv>client</jv>
1551    *       .formPost(<jsf>URI</jsf>)
1552    *       .formData(
1553    *          <js>"foo"</js>, AList.<jsm>of</jsm>(<js>"bar"</js>,<js>"baz"</js>),
1554    *          HttpPartSchema.<jsf>T_ARRAY_PIPES</jsf>
1555    *    )
1556    *       .run();
1557    * </p>
1558    *
1559    * @param name The parameter name.
1560    * @param value The parameter value.
1561    *    <ul>
1562    *       <li>Value can be any POJO or POJO {@link Supplier}.
1563    *       <li>Value converted to a string using the configured part serializer.
1564    *    </ul>
1565    * @param schema The HTTP part schema.  Can be <jk>null</jk>.
1566    * @return This object (for method chaining).
1567    * @throws RestCallException Invalid input.
1568    */
1569   public RestRequest formData(String name, Object value, HttpPartSchema schema) throws RestCallException {
1570      return formDatas(serializedNameValuePair(name, value, FORMDATA, partSerializer, schema, null));
1571   }
1572
1573   /**
1574    * Adds a form-data parameter to the request body.
1575    *
1576    * <h5 class='section'>Example:</h5>
1577    * <p class='bcode w800'>
1578    *    <jc>// Adds form data parameter "foo=bar".</jc>
1579    *    <jv>client</jv>
1580    *       .formPost(<jsf>URI</jsf>)
1581    *       .formData(
1582    *          <jsf>APPEND</jsf>,
1583    *          <js>"foo"</js>, <js>"bar"</js>
1584    *    )
1585    *       .run();
1586    * </p>
1587    *
1588    * @param flag How to add this parameter.
1589    *    <ul>
1590    *       <li>{@link AddFlag#APPEND APPEND} (default) - Append to end.
1591    *       <li>{@link AddFlag#PREPEND PREPEND} - Prepend to beginning.
1592    *       <li>{@link AddFlag#REPLACE REPLACE} - Delete any existing with same name and append to end.
1593    *    </ul>
1594    * @param name The parameter name.
1595    * @param value The parameter value.
1596    *    <ul>
1597    *       <li>Value can be any POJO or POJO {@link Supplier}.
1598    *       <li>Value converted to a string using the configured part serializer.
1599    *    </ul>
1600    * @return This object (for method chaining).
1601    * @throws RestCallException Invalid input.
1602    */
1603   public RestRequest formData(AddFlag flag, String name, Object value) throws RestCallException {
1604      return formDatas(flag, serializedNameValuePair(name, value, FORMDATA, partSerializer, null, EnumSet.of(flag)));
1605   }
1606
1607   /**
1608    * Adds a form-data parameter to the request body.
1609    *
1610    * <h5 class='section'>Example:</h5>
1611    * <p class='bcode w800'>
1612    *    <jc>// Adds form data parameters "foo=bar&baz=qux".</jc>
1613    *    <jv>client</jv>
1614    *       .formPost(<jsf>URI</jsf>)
1615    *       .formDatas(
1616    *          BasicNameValuePair.<jsm>of</jsm>(<js>"foo"</js>,<js>"bar"</js>),
1617    *          AMap.<jsm>of</jsm>(<js>"baz"</js>,<js>"qux"</js>)
1618    *       )
1619    *       .run();
1620    * </p>
1621    *
1622    * @param params
1623    *    The parameters to set.
1624    *    <br>Can be any of the following types:
1625    *    <ul>
1626    *       <li>{@link NameValuePair}
1627    *       <li>{@link NameValuePairable}
1628    *       <li>{@link java.util.Map.Entry}
1629    *       <li>{@link NameValuePairSupplier}
1630    *       <li>{@link Map}
1631    *       <ul>
1632    *          <li>Values can be any POJO.
1633    *          <li>Values converted to a string using the configured part serializer.
1634    *       </ul>
1635    *       <li>A collection or array of anything on this list.
1636    * </ul>
1637    * @return This object (for method chaining).
1638    * @throws RestCallException Invalid input.
1639    */
1640   public RestRequest formDatas(Object...params) throws RestCallException {
1641      return formDatas(APPEND, params);
1642   }
1643
1644   /**
1645    * Adds multiple form-data parameters to the request body.
1646    *
1647    * <h5 class='section'>Example:</h5>
1648    * <p class='bcode w800'>
1649    *    <jc>// Adds form data parameters "foo=bar&baz=qux".</jc>
1650    *    <jv>client</jv>
1651    *       .formPost(<jsf>URI</jsf>)
1652    *       .formDatas(
1653    *          <jsf>APPEND</jsf>,
1654    *          BasicNameValuePair.<jsm>of</jsm>(<js>"foo"</js>,<js>"bar"</js>),
1655    *          AMap.<jsm>of</jsm>(<js>"baz"</js>,<js>"qux"</js>)
1656    *       )
1657    *       .run();
1658    * </p>
1659    *
1660    * @param flag How to add this parameter.
1661    *    <ul>
1662    *       <li>{@link AddFlag#APPEND APPEND} (default) - Append to end.
1663    *       <li>{@link AddFlag#PREPEND PREPEND} - Prepend to beginning.
1664    *       <li>{@link AddFlag#REPLACE REPLACE} - Delete any existing with same name and append to end.
1665    *    </ul>
1666    * @param params
1667    *    The parameters to set.
1668    *    <br>Can be any of the following types:
1669    *    <ul>
1670    *       <li>{@link NameValuePair}
1671    *       <li>{@link NameValuePairable}
1672    *       <li>{@link java.util.Map.Entry}
1673    *       <li>{@link NameValuePairSupplier}
1674    *       <li>{@link Map}
1675    *       <ul>
1676    *          <li>Values can be any POJO.
1677    *          <li>Values converted to a string using the configured part serializer.
1678    *       </ul>
1679    *       <li>A collection or array of anything on this list.
1680    * </ul>
1681    * @return This object (for method chaining).
1682    * @throws RestCallException Invalid input.
1683    */
1684   public RestRequest formDatas(AddFlag flag, Object...params) throws RestCallException {
1685      List<NameValuePair> l = new ArrayList<>();
1686      for (Object o : params) {
1687         if (BasicNameValuePair.canCast(o)) {
1688            l.add(BasicNameValuePair.cast(o));
1689         } else if (o instanceof NameValuePairSupplier) {
1690            for (NameValuePair p : (NameValuePairSupplier)o)
1691               l.add(p);
1692         } else if (o instanceof Collection) {
1693            for (Object o2 : (Collection<?>)o)
1694               l.add(BasicNameValuePair.cast(o2));
1695         } else if (o != null && o.getClass().isArray()) {
1696            for (int i = 0; i < Array.getLength(o); i++)
1697               l.add(BasicNameValuePair.cast(Array.get(o, i)));
1698         } else if (o instanceof Map) {
1699            for (Map.Entry<Object,Object> e : toMap(o).entrySet())
1700               l.add(serializedNameValuePair(e.getKey(), e.getValue(), FORMDATA, partSerializer, null, EnumSet.of(flag)));
1701         } else if (isBean(o)) {
1702            for (Map.Entry<String,Object> e : toBeanMap(o).entrySet())
1703               l.add(serializedNameValuePair(e.getKey(), e.getValue(), FORMDATA, partSerializer, null, EnumSet.of(flag)));
1704         } else if (o != null) {
1705            throw new RestCallException(null, null, "Invalid type passed to formDatas(): {0}", className(o));
1706         }
1707      }
1708      return innerFormData(EnumSet.of(flag), l);
1709   }
1710
1711   /**
1712    * Adds form-data parameters to the request body using free-form key/value pairs.
1713    *
1714    * <h5 class='section'>Example:</h5>
1715    * <p class='bcode w800'>
1716    *    <jc>// Creates form data "key1=val1&key2=val2".</jc>
1717    *    <jv>client</jv>
1718    *       .formPost(<jsf>URI</jsf>)
1719    *       .formDataPairs(<js>"key1"</js>,<js>"val1"</js>,<js>"key2"</js>,<js>"val2"</js>)
1720    *       .run();
1721    * </p>
1722    *
1723    * @param pairs The form-data key/value pairs.
1724    *    <ul>
1725    *       <li>Values can be any POJO.
1726    *       <li>Values converted to a string using the configured part serializer.
1727    *    </ul>
1728    * @return This object (for method chaining).
1729    * @throws RestCallException Invalid input.
1730    */
1731   public RestRequest formDataPairs(Object...pairs) throws RestCallException {
1732      if (pairs.length % 2 != 0)
1733         throw new RestCallException(null, null, "Odd number of parameters passed into formDataPairs()");
1734      for (int i = 0; i < pairs.length; i+=2)
1735         formDatas(serializedNameValuePair(pairs[i], pairs[i+1], FORMDATA, partSerializer, null, null));
1736      return this;
1737   }
1738
1739   /**
1740    * Adds form-data parameters as the entire body of the request.
1741    *
1742    * <h5 class='section'>Example:</h5>
1743    * <p class='bcode w800'>
1744    *    <jc>// Creates form data "foo=bar&baz=qux".</jc>
1745    *    <jv>client</jv>
1746    *       .formPost(<jsf>URI</jsf>)
1747    *       .formDataCustom(<js>"foo=bar&baz=qux"</js>)
1748    *       .run();
1749    *
1750    *    <jc>// Creates form data "foo=bar&baz=qux" using StringEntity.</jc>
1751    *    <jv>client</jv>
1752    *       .formPost(<jsf>URI</jsf>)
1753    *       .formDataCustom(<jk>new</jk> StringEntity(<js>"foo=bar&baz=qux"</js>,<js>"application/x-www-form-urlencoded"</js>))
1754    *       .run();
1755    *
1756    *    <jc>// Creates form data "foo=bar&baz=qux" using StringEntity and body().</jc>
1757    *    <jv>client</jv>
1758    *       .formPost(<jsf>URI</jsf>)
1759    *       .body(<jk>new</jk> StringEntity(<js>"foo=bar&baz=qux"</js>,<js>"application/x-www-form-urlencoded"</js>))
1760    *       .run();
1761    * </p>
1762    *
1763    * @param value The parameter value.
1764    *    <br>Can be any of the following types:
1765    *    <ul class='spaced-list'>
1766    *       <li>
1767    *          {@link CharSequence}
1768    *       <li>
1769    *          {@link Reader} - Raw contents of {@code Reader} will be serialized to remote resource.
1770    *       <li>
1771    *          {@link InputStream} - Raw contents of {@code InputStream} will be serialized to remote resource.
1772    *       <li>
1773    *          {@link HttpResource}/{@link BasicHttpResource} - Raw contents will be serialized to remote resource.  Additional headers and media type will be set on request.
1774    *       <li>
1775    *          {@link HttpEntity}/{@link BasicHttpEntity} - Bypass Juneau serialization and pass HttpEntity directly to HttpClient.
1776    *       <li>
1777    *          {@link Object} - POJO to be converted to text using the {@link Serializer} registered with the
1778    *          {@link RestClient}.
1779    *       <li>
1780    *          {@link NameValuePairSupplier} - Converted to a URL-encoded FORM post.
1781    *    </ul>
1782    * @return This object (for method chaining).
1783    * @throws RestCallException Invalid input.
1784    */
1785   public RestRequest formDataCustom(Object value) throws RestCallException {
1786      contentType("application/x-www-form-urlencoded");
1787      body(value instanceof CharSequence ? new StringReader(value.toString()) : value);
1788      return this;
1789   }
1790
1791   RestRequest formDataArg(EnumSet<AddFlag> flags, String name, Object value, HttpPartSchema schema, HttpPartSerializerSession serializer) throws RestCallException {
1792      flags = AddFlag.orDefault(flags);
1793      boolean isMulti = isEmpty(name) || "*".equals(name) || value instanceof NameValuePairSupplier || isNameValuePairArray(value);
1794
1795      if (! isMulti)
1796         return innerFormData(flags, AList.of(serializedNameValuePair(name, value, FORMDATA, serializer, schema, flags)));
1797
1798      List<NameValuePair> l = AList.of();
1799
1800      if (BasicNameValuePair.canCast(value)) {
1801         l.add(BasicNameValuePair.cast(value));
1802      } else if (value instanceof NameValuePairSupplier) {
1803         for (Object o : (NameValuePairSupplier)value)
1804            l.add(BasicNameValuePair.cast(o));
1805      } else if (value instanceof Collection) {
1806         for (Object o : (Collection<?>)value)
1807            l.add(BasicNameValuePair.cast(o));
1808      } else if (value != null && value.getClass().isArray()) {
1809         for (int i = 0; i < Array.getLength(value); i++)
1810            l.add(BasicNameValuePair.cast(Array.get(value, i)));
1811      } else if (value instanceof Map) {
1812         for (Map.Entry<Object,Object> e : toMap(value).entrySet())
1813            l.add(serializedNameValuePair(e.getKey(), e.getValue(), FORMDATA, serializer, schema, flags));
1814      } else if (isBean(value)) {
1815         for (Map.Entry<String,Object> e : toBeanMap(value).entrySet())
1816            l.add(serializedNameValuePair(e.getKey(), e.getValue(), FORMDATA, serializer, schema, flags));
1817      } else {
1818         return formDataCustom(value);
1819      }
1820
1821      return innerFormData(flags, l);
1822   }
1823
1824   private RestRequest innerFormData(EnumSet<AddFlag> flags, List<NameValuePair> params) {
1825      input = null;
1826      flags = AddFlag.orDefault(flags);
1827      params.removeIf(x -> x.getValue() == null);
1828      if (flags.contains(SKIP_IF_EMPTY))
1829         params.removeIf(x -> isEmpty(x.getValue()));
1830      if (formData == null)
1831         formData = new ArrayList<>();
1832      if (flags.contains(REPLACE)) {
1833         for (NameValuePair p : params)
1834            for (Iterator<NameValuePair> i = formData.iterator(); i.hasNext();)
1835               if (i.next().getName().equals(p.getName()))
1836                  i.remove();
1837         formData.addAll(params);
1838      } else if (flags.contains(PREPEND)) {
1839         formData.addAll(0, params);
1840      } else {
1841         formData.addAll(params);
1842      }
1843      return this;
1844   }
1845
1846
1847   //------------------------------------------------------------------------------------------------------------------
1848   // Request body
1849   //------------------------------------------------------------------------------------------------------------------
1850
1851   /**
1852    * Sets the body of this request.
1853    *
1854    * @param input
1855    *    The input to be sent to the REST resource (only valid for PUT/POST/PATCH) requests.
1856    *    <br>Can be of the following types:
1857    *    <ul class='spaced-list'>
1858    *       <li>
1859    *          {@link Reader} - Raw contents of {@code Reader} will be serialized to remote resource.
1860    *       <li>
1861    *          {@link InputStream} - Raw contents of {@code InputStream} will be serialized to remote resource.
1862    *       <li>
1863    *          {@link HttpResource}/{@link BasicHttpResource} - Raw contents will be serialized to remote resource.  Additional headers and media type will be set on request.
1864    *       <li>
1865    *          {@link HttpEntity}/{@link BasicHttpEntity} - Bypass Juneau serialization and pass HttpEntity directly to HttpClient.
1866    *       <li>
1867    *          {@link Object} - POJO to be converted to text using the {@link Serializer} registered with the
1868    *          {@link RestClient}.
1869    *       <li>
1870    *          {@link NameValuePairSupplier} - Converted to a URL-encoded FORM post.
1871    *       <li>
1872    *          A {@link Supplier} of anything on this list.
1873    *    </ul>
1874    * @return This object (for method chaining).
1875    * @throws RestCallException If a retry was attempted, but the entity was not repeatable.
1876    */
1877   public RestRequest body(Object input) throws RestCallException {
1878      this.input = input;
1879      this.hasInput = true;
1880      this.formData = null;
1881      return this;
1882   }
1883
1884   /**
1885    * Sets the body of this request as straight text bypassing the serializer.
1886    *
1887    * <p class='bcode w800'>
1888    *    <jv>client</jv>
1889    *       .put(<js>"/foo"</js>)
1890    *       .body(<jk>new</jk> StringReader(<js>"foo"</js>))
1891    *       .contentType(""
1892    *       .run();
1893    *
1894    * <jv>client</jv>
1895    *       .put(<js>"/foo"</js>)
1896    *       .bodyString(<js>"foo"</js>)
1897    *       .run();
1898    * </p>
1899    *
1900    * <p>
1901    * Note that this is different than the following which will serialize <l>foo</l> as a JSON string <l>"foo"</l>.
1902    * <p class='bcode w800'>
1903    *    <jv>client</jv>
1904    *       .put(<js>"/foo"</js>)
1905    *       .json()
1906    *       .body(<js>"foo"</js>)
1907    *       .run();
1908    * </p>
1909    *
1910    * @param input
1911    *    The input to be sent to the REST resource (only valid for PUT/POST/PATCH) requests.
1912    * @return This object (for method chaining).
1913    * @throws RestCallException If a retry was attempted, but the entity was not repeatable.
1914    */
1915   public RestRequest bodyString(Object input) throws RestCallException {
1916      return body(input == null ? null : new StringReader(stringify(input)));
1917   }
1918
1919   /**
1920    * Sets the body of this request.
1921    *
1922    * @param input
1923    *    The input to be sent to the REST resource (only valid for PUT/POST/PATCH) requests.
1924    *    <br>Can be of the following types:
1925    *    <ul class='spaced-list'>
1926    *       <li>
1927    *          {@link Reader} - Raw contents of {@code Reader} will be serialized to remote resource.
1928    *       <li>
1929    *          {@link InputStream} - Raw contents of {@code InputStream} will be serialized to remote resource.
1930    *       <li>
1931    *          {@link HttpResource}/{@link BasicHttpResource} - Raw contents will be serialized to remote resource.  Additional headers and media type will be set on request.
1932    *       <li>
1933    *          {@link HttpEntity}/{@link BasicHttpEntity} - Bypass Juneau serialization and pass HttpEntity directly to HttpClient.
1934    *       <li>
1935    *          {@link Object} - POJO to be converted to text using the {@link Serializer} registered with the
1936    *          {@link RestClient}.
1937    *       <li>
1938    *          {@link NameValuePairSupplier} - Converted to a URL-encoded FORM post.
1939    *       <li>
1940    *          A {@link Supplier} of anything on this list.
1941    *    </ul>
1942    * @param schema The schema object that defines the format of the output.
1943    *    <ul>
1944    *       <li>If <jk>null</jk>, defaults to {@link HttpPartSchema#DEFAULT}.
1945    *       <li>Only used if serializer is schema-aware (e.g. {@link OpenApiSerializer}).
1946    *    </ul>
1947    * @return This object (for method chaining).
1948    * @throws RestCallException If a retry was attempted, but the entity was not repeatable.
1949    */
1950   public RestRequest body(Object input, HttpPartSchema schema) throws RestCallException {
1951      this.input = input;
1952      this.hasInput = true;
1953      this.formData = null;
1954      this.requestBodySchema = schema;
1955      return this;
1956   }
1957
1958   //-----------------------------------------------------------------------------------------------------------------
1959   // Headers
1960   //-----------------------------------------------------------------------------------------------------------------
1961
1962   /**
1963    * Adds a header on the request.
1964    *
1965    * <h5 class='section'>Example:</h5>
1966    * <p class='bcode w800'>
1967    *    <jc>// Adds header "Foo: bar|baz".</jc>
1968    *    <jv>client</jv>
1969    *       .get(<jsf>URI</jsf>)
1970    *       .header(
1971    *          <jsf>APPEND</jsf>,
1972    *          <js>"Foo"</js>, AList.<jsm>of</jsm>(<js>"bar"</js>,<js>"baz"</js>)),
1973    *          HttpPartSchema.<jsf>T_ARRAY_PIPES</jsf>
1974    *       )
1975    *       .run();
1976    * </p>
1977    *
1978    * @param flag How to add this parameter.
1979    *    <ul>
1980    *       <li>{@link AddFlag#APPEND APPEND} (default) - Append to end.
1981    *       <li>{@link AddFlag#PREPEND PREPEND} - Prepend to beginning.
1982    *       <li>{@link AddFlag#REPLACE REPLACE} - Delete any existing with same name and append to end.
1983    *    </ul>
1984    * @param name The header name.
1985    * @param value The header value.
1986    *    <ul>
1987    *       <li>Value can be any POJO or POJO {@link Supplier}.
1988    *       <li>Value converted to a string using the configured part serializer.
1989    *    </ul>
1990    * @param schema The schema object that defines the format of the output.
1991    *    <ul>
1992    *       <li>If <jk>null</jk>, defaults to {@link HttpPartSchema#DEFAULT}.
1993    *       <li>Only used if serializer is schema-aware (e.g. {@link OpenApiSerializer}).
1994    *    </ul>
1995    * @return This object (for method chaining).
1996    * @throws RestCallException Invalid input.
1997    */
1998   public RestRequest header(AddFlag flag, String name, Object value, HttpPartSchema schema) throws RestCallException {
1999      return headers(flag, serializedHeader(name, value, partSerializer, schema, EnumSet.of(flag)));
2000   }
2001
2002   /**
2003    * Appends a header on the request.
2004    *
2005    * <h5 class='section'>Example:</h5>
2006    * <p class='bcode w800'>
2007    *    <jc>// Adds header "Foo: bar".</jc>
2008    *    <jv>client</jv>
2009    *       .get(<jsf>URI</jsf>)
2010    *       .header(<js>"Foo"</js>, <js>"bar"</js>)
2011    *       .run();
2012    * </p>
2013    *
2014    * @param name The header name.
2015    * @param value The header value.
2016    *    <ul>
2017    *       <li>Value can be any POJO or POJO {@link Supplier}.
2018    *       <li>Value converted to a string using the configured part serializer.
2019    *    </ul>
2020    * @return This object (for method chaining).
2021    * @throws RestCallException Invalid input.
2022    */
2023   public RestRequest header(String name, Object value) throws RestCallException {
2024      return headers(serializedHeader(name, value, partSerializer, null, null));
2025   }
2026
2027   /**
2028    * Appends a header on the request.
2029    *
2030    * <p>
2031    * The optional schema allows for specifying how part should be serialized (as a pipe-delimited list for example).
2032    *
2033    * <h5 class='section'>Example:</h5>
2034    * <p class='bcode w800'>
2035    *    <jc>// Adds header "Foo: bar|baz".</jc>
2036    *    <jv>client</jv>
2037    *       .get(<jsf>URI</jsf>)
2038    *       .header(
2039    *          <js>"Foo"</js>, AList.<jsm>of</jsm>(<js>"bar"</js>,<js>"baz"</js>),
2040    *          HttpPartSchema.<jsf>T_ARRAY_PIPES</jsf>
2041    *       )
2042    *       .run();
2043    * </p>
2044    *
2045    * @param name The header name.
2046    * @param value The header value.
2047    *    <ul>
2048    *       <li>Value can be any POJO or POJO {@link Supplier}.
2049    *       <li>Value converted to a string using the configured part serializer.
2050    *    </ul>
2051    * @param schema The HTTP part schema.  Can be <jk>null</jk>.
2052    * @return This object (for method chaining).
2053    * @throws RestCallException Invalid input.
2054    */
2055   public RestRequest header(String name, Object value, HttpPartSchema schema) throws RestCallException {
2056      return headers(serializedHeader(name, value, partSerializer, schema, null));
2057   }
2058
2059   /**
2060    * Adds a header to the request.
2061    *
2062    * <h5 class='section'>Example:</h5>
2063    * <p class='bcode w800'>
2064    *    <jc>// Adds header "Foo: bar".</jc>
2065    *    <jv>client</jv>
2066    *       .get(<jsf>URI</jsf>)
2067    *       .header(
2068    *          <jsf>APPEND</jsf>,
2069    *          <js>"Foo"</js>, <js>"bar"</js>
2070    *       )
2071    *       .run();
2072    * </p>
2073    *
2074    * @param flag How to add this parameter.
2075    *    <ul>
2076    *       <li>{@link AddFlag#APPEND APPEND} (default) - Append to end.
2077    *       <li>{@link AddFlag#PREPEND PREPEND} - Prepend to beginning.
2078    *    <li>{@link AddFlag#REPLACE REPLACE} - Delete any existing with same name and append to end.
2079    *    </ul>
2080    * @param name The header name.
2081    * @param value The header value.
2082    *    <ul>
2083    *       <li>Value can be any POJO or POJO {@link Supplier}.
2084    *       <li>Value converted to a string using the configured part serializer.
2085    *    </ul>
2086    * @return This object (for method chaining).
2087    * @throws RestCallException Invalid input.
2088    */
2089   public RestRequest header(AddFlag flag, String name, Object value) throws RestCallException {
2090      return headers(flag, serializedHeader(name, value, partSerializer, null, EnumSet.of(flag)));
2091   }
2092
2093   /**
2094    * Appends a header on the request.
2095    *
2096    * <h5 class='section'>Example:</h5>
2097    * <p class='bcode w800'>
2098    *    <jc>// Adds header "Foo: bar".</jc>
2099    *    <jv>client</jv>
2100    *       .get(<jsf>URI</jsf>)
2101    *       .header(BasicHeader.<jsm>of</jsm>(<js>"Foo"</js>, <js>"bar"</js>))
2102    *       .run();
2103    * </p>
2104    *
2105    * @param header The header to set.
2106    * @return This object (for method chaining).
2107    * @throws RestCallException Invalid input.
2108    */
2109   public RestRequest header(Header header) throws RestCallException {
2110      return headers(header);
2111   }
2112
2113   /**
2114    * Appends multiple headers to the request.
2115    *
2116    * <h5 class='section'>Example:</h5>
2117    * <p class='bcode w800'>
2118    *    <jc>// Adds headers "Foo: bar" and "Baz: qux".</jc>
2119    *    <jv>client</jv>
2120    *       .get(<jsf>URI</jsf>)
2121    *       .headers(
2122    *          BasicHeader.<jsm>of</jsm>(<js>"Foo"</js>, <js>"bar"</js>),
2123    *          AMap.<jsm>of</jsm>(<js>"Baz"</js>, <js>"qux"</js>)
2124    *       )
2125    *       .run();
2126    * </p>
2127    *
2128    * @param headers
2129    *    The headers to set.
2130    *    <br>Can be any of the following types:
2131    *    <ul>
2132    *       <li>{@link Header} (including any subclasses such as {@link Accept})
2133    *       <li>{@link Headerable}
2134    *       <li>{@link java.util.Map.Entry}
2135    *       <li>{@link HeaderSupplier}
2136    *       <li>{@link Map}
2137    *       <ul>
2138    *          <li>Values can be any POJO.
2139    *          <li>Values converted to a string using the configured part serializer.
2140    *       </ul>
2141    *       <li>A collection or array of anything on this list.
2142    * </ul>
2143    * @return This object (for method chaining).
2144    * @throws RestCallException Invalid input.
2145    */
2146   public RestRequest headers(Object...headers) throws RestCallException {
2147      return headers(APPEND, headers);
2148   }
2149
2150   /**
2151    * Sets multiple headers on the request.
2152    *
2153    * <h5 class='section'>Example:</h5>
2154    * <p class='bcode w800'>
2155    *    <jc>// Adds headers "Foo: bar" and "Baz: qux".</jc>
2156    *    <jv>client</jv>
2157    *       .get(<jsf>URI</jsf>)
2158    *       .headers(
2159    *          <jsf>APPEND</jsf>,
2160    *          BasicHeader.<jsm>of</jsm>(<js>"Foo"</js>, <js>"bar"</js>),
2161    *          AMap.<jsm>of</jsm>(<js>"Baz"</js>, <js>"qux"</js>)
2162    *       )
2163    *       .run();
2164    * </p>
2165    *
2166    * @param flag How to add this parameter.
2167    *    <ul>
2168    *       <li>{@link AddFlag#APPEND APPEND} (default) - Append to end.
2169    *       <li>{@link AddFlag#PREPEND PREPEND} - Prepend to beginning.
2170    *       <li>{@link AddFlag#REPLACE REPLACE} - Delete any existing with same name and append to end.
2171    *    </ul>
2172    * @param headers
2173    *    The headers to set.
2174    *    <br>Can be any of the following types:
2175    *    <ul>
2176    *       <li>{@link Header} (including any subclasses such as {@link Accept})
2177    *       <li>{@link Headerable}
2178    *       <li>{@link java.util.Map.Entry}
2179    *       <li>{@link HeaderSupplier}
2180    *       <li>{@link Map}
2181    *       <ul>
2182    *          <li>Values can be any POJO.
2183    *          <li>Values converted to a string using the configured part serializer.
2184    *       </ul>
2185    *       <li>A collection or array of anything on this list.
2186    * </ul>
2187    * @return This object (for method chaining).
2188    * @throws RestCallException Invalid input.
2189    */
2190   public RestRequest headers(AddFlag flag, Object...headers) throws RestCallException {
2191      List<Header> l = new ArrayList<>();
2192      for (Object o : headers) {
2193         if (BasicHeader.canCast(o)) {
2194            l.add(BasicHeader.cast(o));
2195         } else if (o instanceof HeaderSupplier) {
2196            for (Header h : (HeaderSupplier)o)
2197               l.add(h);
2198         } else if (o instanceof Collection) {
2199            for (Object o2 : (Collection<?>)o)
2200               l.add(BasicHeader.cast(o2));
2201         } else if (o != null && o.getClass().isArray()) {
2202            for (int i = 0; i < Array.getLength(o); i++)
2203               l.add(BasicHeader.cast(Array.get(o, i)));
2204         } else if (o instanceof Map) {
2205            for (Map.Entry<Object,Object> e : toMap(o).entrySet())
2206               l.add(serializedHeader(e.getKey(), e.getValue(), partSerializer, null, EnumSet.of(flag)));
2207         } else if (isBean(o)) {
2208            for (Map.Entry<String,Object> e : toBeanMap(o).entrySet())
2209               l.add(serializedHeader(e.getKey(), e.getValue(), partSerializer, null, EnumSet.of(flag)));
2210         } else if (o != null) {
2211            throw new RestCallException(null, null, "Invalid type passed to headers(): {0}", className(o));
2212         }
2213      }
2214      return innerHeaders(EnumSet.of(flag), l);
2215   }
2216
2217   /**
2218    * Appends multiple headers on the request using freeform key/value pairs.
2219    *
2220    * <h5 class='section'>Example:</h5>
2221    * <p class='bcode w800'>
2222    *    <jc>// Adds headers "Foo: bar" and "Baz: qux".</jc>
2223    *    <jv>client</jv>
2224    *       .get(<jsf>URI</jsf>)
2225    *       .headers(<js>"Foo"</js>,<js>"bar"</js>,<js>"Baz"</js>,<js>"qux"</js>)
2226    *       .run();
2227    * </p>
2228    *
2229    * @param pairs The form-data key/value pairs.
2230    *    <ul>
2231    *       <li>Values can be any POJO.
2232    *       <li>Values converted to a string using the configured part serializer.
2233    *    </ul>
2234    * @return This object (for method chaining).
2235    * @throws RestCallException Invalid input.
2236    */
2237   public RestRequest headerPairs(Object...pairs) throws RestCallException {
2238      List<Header> l = new ArrayList<>();
2239      if (pairs.length % 2 != 0)
2240         throw new RestCallException(null, null, "Odd number of parameters passed into headerPairs()");
2241      for (int i = 0; i < pairs.length; i+=2)
2242         l.add(serializedHeader(pairs[i], pairs[i+1], partSerializer, null, null));
2243      return innerHeaders(EnumSet.of(APPEND), l);
2244   }
2245
2246   RestRequest headerArg(EnumSet<AddFlag> flags, String name, Object value, HttpPartSchema schema, HttpPartSerializerSession serializer) throws RestCallException {
2247      flags = AddFlag.orDefault(flags);
2248      boolean isMulti = isEmpty(name) || "*".equals(name) || value instanceof HeaderSupplier || isHeaderArray(value);
2249
2250      if (! isMulti)
2251         return innerHeaders(flags, AList.of(serializedHeader(name, value, serializer, schema, flags)));
2252
2253      List<Header> l = AList.of();
2254
2255      if (BasicHeader.canCast(value)) {
2256         l.add(BasicHeader.cast(value));
2257      } else if (value instanceof HeaderSupplier) {
2258         for (Object o : (HeaderSupplier)value)
2259            l.add(BasicHeader.cast(o));
2260      } else if (value instanceof Collection) {
2261         for (Object o : (Collection<?>)value)
2262            l.add(BasicHeader.cast(o));
2263      } else if (value != null && value.getClass().isArray()) {
2264         for (int i = 0; i < Array.getLength(value); i++)
2265            l.add(BasicHeader.cast(Array.get(value, i)));
2266      } else if (value instanceof Map) {
2267         for (Map.Entry<Object,Object> e : toMap(value).entrySet())
2268            l.add(serializedHeader(e.getKey(), e.getValue(), serializer, schema, flags));
2269      } else if (isBean(value)) {
2270         for (Map.Entry<String,Object> e : toBeanMap(value).entrySet())
2271            l.add(serializedHeader(e.getKey(), e.getValue(), serializer, schema, flags));
2272      } else if (value != null) {
2273         throw new RestCallException(null, null, "Invalid value type for header arg ''{0}'': {1}", name, className(value));
2274      }
2275
2276      return innerHeaders(flags, l);
2277   }
2278
2279   private RestRequest innerHeaders(EnumSet<AddFlag> flags, Collection<Header> headers) {
2280      flags = AddFlag.orDefault(flags);
2281      headers.removeIf(x -> x.getValue() == null);
2282      if (flags.contains(SKIP_IF_EMPTY))
2283         headers.removeIf(x -> isEmpty(x.getValue()));
2284      if (flags.contains(REPLACE)) {
2285         for (Header h : headers)
2286            removeHeaders(h.getName());
2287      } else if (flags.contains(PREPEND)) {
2288         for (Header h : AList.of(headers)) {
2289            for (Header h2 : getHeaders(h.getName()))
2290               headers.add(h2);
2291            removeHeaders(h.getName());
2292         }
2293      }
2294      for (Header h : headers) {
2295         addHeader(h);
2296      }
2297      return this;
2298   }
2299
2300   /**
2301    * Convenience method for reading the current last value of the specified header.
2302    *
2303    * @param name The header name.
2304    * @return The header value or <jk>null</jk> if not set.
2305    */
2306   public String getHeader(String name) {
2307      return getHeader(name, null);
2308   }
2309
2310   /**
2311    * Convenience method for reading the current last value of the specified header.
2312    *
2313    * @param name The header name.
2314    * @param def The default value if the header is not set.
2315    * @return The header value or the default value if not set.
2316    */
2317   public String getHeader(String name, String def) {
2318      Header h = getLastHeader(name);
2319      return h == null ? def : h.getValue();
2320   }
2321
2322   //------------------------------------------------------------------------------------------------------------------
2323   // Specialized headers.
2324   //------------------------------------------------------------------------------------------------------------------
2325
2326   /**
2327    * Sets the value for the <c>Accept</c> request header.
2328    *
2329    * <p>
2330    * This overrides the media type specified on the parser, but is overridden by calling
2331    * <code>header(<js>"Accept"</js>, value);</code>
2332    *
2333    * @param value The new header value.
2334    * @return This object (for method chaining).
2335    * @throws RestCallException Invalid input.
2336    */
2337   public RestRequest accept(Object value) throws RestCallException {
2338      return header("Accept", value);
2339   }
2340
2341   /**
2342    * Sets the value for the <c>Accept-Charset</c> request header.
2343    *
2344    * <p>
2345    * This is a shortcut for calling <code>header(<js>"Accept-Charset"</js>, value);</code>
2346    *
2347    * @param value The new header value.
2348    * @return This object (for method chaining).
2349    * @throws RestCallException Invalid input.
2350    */
2351   public RestRequest acceptCharset(Object value) throws RestCallException {
2352      return header("Accept-Charset", value);
2353   }
2354
2355   /**
2356    * Sets the value for the <c>Accept-Encoding</c> request header.
2357    *
2358    * <p>
2359    * This is a shortcut for calling <code>header(<js>"Accept-Encoding"</js>, value);</code>
2360    *
2361    * @param value The new header value.
2362    * @return This object (for method chaining).
2363    * @throws RestCallException Invalid input.
2364    */
2365   public RestRequest acceptEncoding(Object value) throws RestCallException {
2366      return header("Accept-Encoding", value);
2367   }
2368
2369   /**
2370    * Sets the value for the <c>Accept-Language</c> request header.
2371    *
2372    * <p>
2373    * This is a shortcut for calling <code>header(<js>"Accept-Language"</js>, value);</code>
2374    *
2375    * @param value The new header value.
2376    * @return This object (for method chaining).
2377    * @throws RestCallException Invalid input.
2378    */
2379   public RestRequest acceptLanguage(Object value) throws RestCallException {
2380      return header("Accept-Language", value);
2381   }
2382
2383   /**
2384    * Sets the value for the <c>Authorization</c> request header.
2385    *
2386    * <p>
2387    * This is a shortcut for calling <code>header(<js>"Authorization"</js>, value);</code>
2388    *
2389    * @param value The new header value.
2390    * @return This object (for method chaining).
2391    * @throws RestCallException Invalid input.
2392    */
2393   public RestRequest authorization(Object value) throws RestCallException {
2394      return header("Authorization", value);
2395   }
2396
2397   /**
2398    * Sets the value for the <c>Cache-Control</c> request header.
2399    *
2400    * <p>
2401    * This is a shortcut for calling <code>header(<js>"Cache-Control"</js>, value);</code>
2402    *
2403    * @param value The new header value.
2404    * @return This object (for method chaining).
2405    * @throws RestCallException Invalid input.
2406    */
2407   public RestRequest cacheControl(Object value) throws RestCallException {
2408      return header("Cache-Control", value);
2409   }
2410
2411   /**
2412    * Sets the value for the <c>Connection</c> request header.
2413    *
2414    * <p>
2415    * This is a shortcut for calling <code>header(<js>"Connection"</js>, value);</code>
2416    *
2417    * @param value The new header value.
2418    * @return This object (for method chaining).
2419    * @throws RestCallException Invalid input.
2420    */
2421   public RestRequest connection(Object value) throws RestCallException {
2422      return header("Connection", value);
2423   }
2424
2425   /**
2426    * Sets the value for the <c>Content-Length</c> request header.
2427    *
2428    * <p>
2429    * This is a shortcut for calling <code>header(<js>"Content-Length"</js>, value);</code>
2430    *
2431    * @param value The new header value.
2432    * @return This object (for method chaining).
2433    * @throws RestCallException Invalid input.
2434    */
2435   public RestRequest contentLength(Object value) throws RestCallException {
2436      return header("Content-Length", value);
2437   }
2438
2439   /**
2440    * Sets the value for the <c>Content-Type</c> request header.
2441    *
2442    * <p>
2443    * This overrides the media type specified on the serializer, but is overridden by calling
2444    * <code>header(<js>"Content-Type"</js>, value);</code>
2445    *
2446    * @param value The new header value.
2447    * @return This object (for method chaining).
2448    * @throws RestCallException Invalid input.
2449    */
2450   public RestRequest contentType(Object value) throws RestCallException {
2451      return header("Content-Type", value);
2452   }
2453
2454   /**
2455    * Sets the value for the <c>Content-Encoding</c> request header.
2456    *
2457    * <p>
2458    * This is a shortcut for calling <code>header(<js>"Content-Encoding"</js>, value);</code>
2459    *
2460    * @param value The new header value.
2461    * @return This object (for method chaining).
2462    * @throws RestCallException Invalid input.
2463    */
2464   public RestRequest contentEncoding(Object value) throws RestCallException {
2465      return header("Content-Encoding", value);
2466   }
2467
2468   /**
2469    * Sets the value for the <c>Date</c> request header.
2470    *
2471    * <p>
2472    * This is a shortcut for calling <code>header(<js>"Date"</js>, value);</code>
2473    *
2474    * @param value The new header value.
2475    * @return This object (for method chaining).
2476    * @throws RestCallException Invalid input.
2477    */
2478   public RestRequest date(Object value) throws RestCallException {
2479      return header("Date", value);
2480   }
2481
2482   /**
2483    * Sets the value for the <c>Expect</c> request header.
2484    *
2485    * <p>
2486    * This is a shortcut for calling <code>header(<js>"Expect"</js>, value);</code>
2487    *
2488    * @param value The new header value.
2489    * @return This object (for method chaining).
2490    * @throws RestCallException Invalid input.
2491    */
2492   public RestRequest expect(Object value) throws RestCallException {
2493      return header("Expect", value);
2494   }
2495
2496   /**
2497    * Sets the value for the <c>Forwarded</c> request header.
2498    *
2499    * <p>
2500    * This is a shortcut for calling <code>header(<js>"Forwarded"</js>, value);</code>
2501    *
2502    * @param value The new header value.
2503    * @return This object (for method chaining).
2504    * @throws RestCallException Invalid input.
2505    */
2506   public RestRequest forwarded(Object value) throws RestCallException {
2507      return header("Forwarded", value);
2508   }
2509
2510   /**
2511    * Sets the value for the <c>From</c> request header.
2512    *
2513    * <p>
2514    * This is a shortcut for calling <code>header(<js>"From"</js>, value);</code>
2515    *
2516    * @param value The new header value.
2517    * @return This object (for method chaining).
2518    * @throws RestCallException Invalid input.
2519    */
2520   public RestRequest from(Object value) throws RestCallException {
2521      return header("From", value);
2522   }
2523
2524   /**
2525    * Sets the value for the <c>Host</c> request header.
2526    *
2527    * <p>
2528    * This is a shortcut for calling <code>header(<js>"Host"</js>, value);</code>
2529    *
2530    * @param value The new header value.
2531    * @return This object (for method chaining).
2532    * @throws RestCallException Invalid input.
2533    */
2534   public RestRequest hostHeader(Object value) throws RestCallException {
2535      return header("Host", value);
2536   }
2537
2538   /**
2539    * Sets the value for the <c>If-Match</c> request header.
2540    *
2541    * <p>
2542    * This is a shortcut for calling <code>header(<js>"If-Match"</js>, value);</code>
2543    *
2544    * @param value The new header value.
2545    * @return This object (for method chaining).
2546    * @throws RestCallException Invalid input.
2547    */
2548   public RestRequest ifMatch(Object value) throws RestCallException {
2549      return header("If-Match", value);
2550   }
2551
2552   /**
2553    * Sets the value for the <c>If-Modified-Since</c> request header.
2554    *
2555    * <p>
2556    * This is a shortcut for calling <code>header(<js>"If-Modified-Since"</js>, value);</code>
2557    *
2558    * @param value The new header value.
2559    * @return This object (for method chaining).
2560    * @throws RestCallException Invalid input.
2561    */
2562   public RestRequest ifModifiedSince(Object value) throws RestCallException {
2563      return header("If-Modified-Since", value);
2564   }
2565
2566   /**
2567    * Sets the value for the <c>If-None-Match</c> request header.
2568    *
2569    * <p>
2570    * This is a shortcut for calling <code>header(<js>"If-None-Match"</js>, value);</code>
2571    *
2572    * @param value The new header value.
2573    * @return This object (for method chaining).
2574    * @throws RestCallException Invalid input.
2575    */
2576   public RestRequest ifNoneMatch(Object value) throws RestCallException {
2577      return header("If-None-Match", value);
2578   }
2579
2580   /**
2581    * Sets the value for the <c>If-Range</c> request header.
2582    *
2583    * <p>
2584    * This is a shortcut for calling <code>header(<js>"If-Range"</js>, value);</code>
2585    *
2586    * @param value The new header value.
2587    * @return This object (for method chaining).
2588    * @throws RestCallException Invalid input.
2589    */
2590   public RestRequest ifRange(Object value) throws RestCallException {
2591      return header("If-Range", value);
2592   }
2593
2594   /**
2595    * Sets the value for the <c>If-Unmodified-Since</c> request header.
2596    *
2597    * <p>
2598    * This is a shortcut for calling <code>header(<js>"If-Unmodified-Since"</js>, value);</code>
2599    *
2600    * @param value The new header value.
2601    * @return This object (for method chaining).
2602    * @throws RestCallException Invalid input.
2603    */
2604   public RestRequest ifUnmodifiedSince(Object value) throws RestCallException {
2605      return header("If-Unmodified-Since", value);
2606   }
2607
2608   /**
2609    * Sets the value for the <c>Max-Forwards</c> request header.
2610    *
2611    * <p>
2612    * This is a shortcut for calling <code>header(<js>"Max-Forwards"</js>, value);</code>
2613    *
2614    * @param value The new header value.
2615    * @return This object (for method chaining).
2616    * @throws RestCallException Invalid input.
2617    */
2618   public RestRequest maxForwards(Object value) throws RestCallException {
2619      return header("Max-Forwards", value);
2620   }
2621
2622   /**
2623    * When called, <c>No-Trace: true</c> is added to requests.
2624    *
2625    * <p>
2626    * This gives the opportunity for the servlet to not log errors on invalid requests.
2627    * This is useful for testing purposes when you don't want your log file to show lots of errors that are simply the
2628    * results of testing.
2629    *
2630    * @return This object (for method chaining).
2631    * @throws RestCallException Invalid input.
2632    */
2633   public RestRequest noTrace() throws RestCallException {
2634      return header("No-Trace", true);
2635   }
2636
2637   /**
2638    * Sets the value for the <c>Origin</c> request header.
2639    *
2640    * <p>
2641    * This is a shortcut for calling <code>header(<js>"Origin"</js>, value);</code>
2642    *
2643    * @param value The new header value.
2644    * @return This object (for method chaining).
2645    * @throws RestCallException Invalid input.
2646    */
2647   public RestRequest origin(Object value) throws RestCallException {
2648      return header("Origin", value);
2649   }
2650
2651   /**
2652    * Sets the value for the <c>Pragma</c> request header.
2653    *
2654    * <p>
2655    * This is a shortcut for calling <code>header(<js>"Pragma"</js>, value);</code>
2656    *
2657    * @param value The new header value.
2658    * @return This object (for method chaining).
2659    * @throws RestCallException Invalid input.
2660    */
2661   public RestRequest pragma(Object value) throws RestCallException {
2662      return header("Pragma", value);
2663   }
2664
2665   /**
2666    * Sets the value for the <c>Proxy-Authorization</c> request header.
2667    *
2668    * <p>
2669    * This is a shortcut for calling <code>header(<js>"Proxy-Authorization"</js>, value);</code>
2670    *
2671    * @param value The new header value.
2672    * @return This object (for method chaining).
2673    * @throws RestCallException Invalid input.
2674    */
2675   public RestRequest proxyAuthorization(Object value) throws RestCallException {
2676      return header("Proxy-Authorization", value);
2677   }
2678
2679   /**
2680    * Sets the value for the <c>Range</c> request header.
2681    *
2682    * <p>
2683    * This is a shortcut for calling <code>header(<js>"Range"</js>, value);</code>
2684    *
2685    * @param value The new header value.
2686    * @return This object (for method chaining).
2687    * @throws RestCallException Invalid input.
2688    */
2689   public RestRequest range(Object value) throws RestCallException {
2690      return header("Range", value);
2691   }
2692
2693   /**
2694    * Sets the value for the <c>Referer</c> request header.
2695    *
2696    * <p>
2697    * This is a shortcut for calling <code>header(<js>"Referer"</js>, value);</code>
2698    *
2699    * @param value The new header value.
2700    * @return This object (for method chaining).
2701    * @throws RestCallException Invalid input.
2702    */
2703   public RestRequest referer(Object value) throws RestCallException {
2704      return header("Referer", value);
2705   }
2706
2707   /**
2708    * Sets the value for the <c>TE</c> request header.
2709    *
2710    * <p>
2711    * This is a shortcut for calling <code>header(<js>"TE"</js>, value);</code>
2712    *
2713    * @param value The new header value.
2714    * @return This object (for method chaining).
2715    * @throws RestCallException Invalid input.
2716    */
2717   public RestRequest te(Object value) throws RestCallException {
2718      return header("TE", value);
2719   }
2720
2721   /**
2722    * Sets the value for the <c>User-Agent</c> request header.
2723    *
2724    * <p>
2725    * This is a shortcut for calling <code>header(<js>"User-Agent"</js>, value);</code>
2726    *
2727    * @param value The new header value.
2728    * @return This object (for method chaining).
2729    * @throws RestCallException Invalid input.
2730    */
2731   public RestRequest userAgent(Object value) throws RestCallException {
2732      return header("User-Agent", value);
2733   }
2734
2735   /**
2736    * Sets the value for the <c>Upgrade</c> request header.
2737    *
2738    * <p>
2739    * This is a shortcut for calling <code>header(<js>"Upgrade"</js>, value);</code>
2740    *
2741    * @param value The new header value.
2742    * @return This object (for method chaining).
2743    * @throws RestCallException Invalid input.
2744    */
2745   public RestRequest upgrade(Object value) throws RestCallException {
2746      return header("Upgrade", value);
2747   }
2748
2749   /**
2750    * Sets the value for the <c>Via</c> request header.
2751    *
2752    * <p>
2753    * This is a shortcut for calling <code>header(<js>"Via"</js>, value);</code>
2754    *
2755    * @param value The new header value.
2756    * @return This object (for method chaining).
2757    * @throws RestCallException Invalid input.
2758    */
2759   public RestRequest via(Object value) throws RestCallException {
2760      return header("Via", value);
2761   }
2762
2763   /**
2764    * Sets the value for the <c>Warning</c> request header.
2765    *
2766    * <p>
2767    * This is a shortcut for calling <code>header(<js>"Warning"</js>, value);</code>
2768    *
2769    * @param value The new header value.
2770    * @return This object (for method chaining).
2771    * @throws RestCallException Invalid input.
2772    */
2773   public RestRequest warning(Object value) throws RestCallException {
2774      return header("Warning", value);
2775   }
2776
2777   /**
2778    * Sets the client version by setting the value for the <js>"X-Client-Version"</js> header.
2779    *
2780    * @param value The version string (e.g. <js>"1.2.3"</js>)
2781    * @return This object (for method chaining).
2782    * @throws RestCallException Invalid input.
2783    */
2784   public RestRequest clientVersion(Object value) throws RestCallException {
2785      return header("X-Client-Version", value);
2786   }
2787
2788   //------------------------------------------------------------------------------------------------------------------
2789   // Execution methods.
2790   //------------------------------------------------------------------------------------------------------------------
2791
2792   /**
2793    * Runs this request and returns the resulting response object.
2794    *
2795    * <h5 class='section'>Example:</h5>
2796    * <p class='bcode w800'>
2797    *    <jk>try</jk> {
2798    *       <jk>int</jk> <jv>rc</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).execute().getResponseStatus();
2799    *       <jc>// Succeeded!</jc>
2800    *    } <jk>catch</jk> (RestCallException <jv>e</jv>) {
2801    *       <jc>// Failed!</jc>
2802    *    }
2803    * </p>
2804    *
2805    * <ul class='notes'>
2806    *    <li>Calling this method multiple times will return the same original response object.
2807    *    <li>You must close the returned object if you do not consume the response or execute a method that consumes
2808    *       the response.
2809    *    <li>If you are only interested in the response code, use the {@link #complete()} method which will automatically
2810    *       consume the response so that you don't need to call {@link InputStream#close()} on the response body.
2811    * </ul>
2812    *
2813    * @return The response object.
2814    * @throws RestCallException If an exception or non-200 response code occurred during the connection attempt.
2815    */
2816   public RestResponse run() throws RestCallException {
2817      if (response != null)
2818         throw new RestCallException(response, null, "run() already called.");
2819
2820      try {
2821         HttpEntityEnclosingRequestBase request2 = request instanceof HttpEntityEnclosingRequestBase ? (HttpEntityEnclosingRequestBase)request : null;
2822         request.setURI(uriBuilder.build());
2823
2824         // Pick the serializer if it hasn't been overridden.
2825         Header h = getLastHeader("Content-Type");
2826         String contentType = h == null ? null : h.getValue();
2827         Serializer serializer = this.serializer;
2828         if (serializer == null)
2829            serializer = client.getMatchingSerializer(contentType);
2830         if (contentType == null && serializer != null)
2831            contentType = serializer.getPrimaryMediaType().toString();
2832
2833         // Pick the parser if it hasn't been overridden.
2834         h = getLastHeader("Accept");
2835         String accept = h == null ? null : h.getValue();
2836         Parser parser = this.parser;
2837         if (parser == null)
2838            parser = client.getMatchingParser(accept);
2839         if (accept == null && parser != null)
2840            setHeader("Accept", parser.getPrimaryMediaType().toString());
2841
2842         if (hasInput || formData != null) {
2843
2844            if (request2 == null)
2845               throw new RestCallException(null, null, "Method does not support content entity.  Method={0}, URI={1}", getMethod(), getURI());
2846
2847            Object input2 = input;
2848
2849            if (input2 instanceof Supplier)
2850               input2 = ((Supplier<?>)input).get();
2851
2852            HttpEntity entity = null;
2853            if (formData != null)
2854               entity = new UrlEncodedFormEntity(formData);
2855            else if (input2 instanceof NameValuePairSupplier)
2856               entity = new UrlEncodedFormEntity((NameValuePairSupplier)input2);
2857            else if (input2 instanceof HttpResource) {
2858               HttpResource r = (HttpResource)input2;
2859               headers(r.getHeaders());
2860               entity = (HttpEntity)input2;
2861            }
2862            else if (input2 instanceof HttpEntity)
2863               entity = (HttpEntity)input2;
2864            else if (input2 instanceof Reader)
2865               entity = new StringEntity(IOUtils.read((Reader)input2), getRequestContentType(TEXT_PLAIN));
2866            else if (input2 instanceof InputStream)
2867               entity = new InputStreamEntity((InputStream)input2, getRequestContentType(ContentType.APPLICATION_OCTET_STREAM));
2868            else if (serializer != null)
2869               entity = SerializedHttpEntity.of(input2, serializer).schema(requestBodySchema).contentType(contentType);
2870            else {
2871               if (input2 == null)
2872                  input2 = "";
2873               entity = new StringEntity(BeanContext.DEFAULT.getClassMetaForObject(input2).toString(input2), getRequestContentType(TEXT_PLAIN));
2874            }
2875
2876            request2.setEntity(entity);
2877         }
2878
2879         try {
2880            response = client.createResponse(this, client.run(target, request, context), parser);
2881         } catch (Exception e) {
2882            throw e;
2883         }
2884
2885         if (isDebug() || client.logRequests == DetailLevel.FULL)
2886            response.cacheBody();
2887
2888         for (RestCallInterceptor rci : interceptors)
2889            rci.onConnect(this, response);
2890         client.onConnect(this, response);
2891
2892         String method = getMethod();
2893         int sc = response.getStatusCode();
2894
2895         if (errorCodes.test(sc) && ! ignoreErrors) {
2896            throw new RestCallException(response, null, "HTTP method ''{0}'' call to ''{1}'' caused response code ''{2}, {3}''.\nResponse: \n{4}",
2897               method, getURI(), sc, response.getReasonPhrase(), response.getBody().asAbbreviatedString(1000));
2898         }
2899
2900      } catch (RuntimeException | RestCallException e) {
2901         if (response != null)
2902            response.close();
2903         throw e;
2904      } catch (Exception e) {
2905         if (response != null)
2906            response.close();
2907         throw new RestCallException(response, e, "Call failed.");
2908      }
2909
2910      return this.response;
2911   }
2912
2913   /**
2914    * Same as {@link #run()} but allows you to run the call asynchronously.
2915    *
2916    * <h5 class='section'>Example:</h5>
2917    * <p class='bcode w800'>
2918    *    Future&lt;RestResponse&gt; <jv>future</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).runFuture();
2919    *
2920    *    <jc>// Do some other stuff</jc>
2921    *
2922    *    <jk>try</jk> {
2923    *       String <jv>body</jv> = <jv>future</jv>.get().getBody().asString();
2924    *       <jc>// Succeeded!</jc>
2925    *    } <jk>catch</jk> (RestCallException <jv>e</jv>) {
2926    *       <jc>// Failed!</jc>
2927    *    }
2928    * </p>
2929    *
2930    * <ul class='notes'>
2931    *    <li>Use the {@link RestClientBuilder#executorService(ExecutorService, boolean)} method to customize the
2932    *       executor service used for creating {@link Future Futures}.
2933    * </ul>
2934    *
2935    * @return The HTTP status code.
2936    * @throws RestCallException If the executor service was not defined.
2937    */
2938   public Future<RestResponse> runFuture() throws RestCallException {
2939      return client.getExecutorService().submit(
2940         new Callable<RestResponse>() {
2941            @Override /* Callable */
2942            public RestResponse call() throws Exception {
2943               return run();
2944            }
2945         }
2946      );
2947   }
2948
2949   /**
2950    * Same as {@link #run()} but immediately calls {@link RestResponse#consume()} to clean up the response.
2951    *
2952    * <p>
2953    * Use this method if you're only interested in the status line of the response and not the response entity.
2954    * Attempts to call any of the methods on the response object that retrieve the body (e.g. {@link RestResponseBody#asReader()}
2955    * will cause a {@link RestCallException} to be thrown.
2956    *
2957    * <ul class='notes'>
2958    *    <li>You do not need to execute {@link InputStream#close()} on the response body to consume the response.
2959    * </ul>
2960    *
2961    * <h5 class='section'>Example:</h5>
2962    * <p class='bcode w800'>
2963    *  <jc>// Get the response code.
2964    *  // No need to call close() on the RestResponse object.</jc>
2965    *  <jk>int</jk> <jv>rc</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).complete().getResponseCode();
2966    * </p>
2967    *
2968    * @return The response object.
2969    * @throws RestCallException If an exception or non-200 response code occurred during the connection attempt.
2970    */
2971   public RestResponse complete() throws RestCallException {
2972      return run().consume();
2973   }
2974
2975   /**
2976    * Same as {@link #complete()} but allows you to run the call asynchronously.
2977    *
2978    * <h5 class='section'>Example:</h5>
2979    * <p class='bcode w800'>
2980    *    Future&lt;RestResponse&gt; <jv>future</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).completeFuture();
2981    *
2982    *    <jc>// Do some other stuff</jc>
2983    *
2984    *    <jk>int</jk> <jv>rc</jv> = <jv>future</jv>.get().getResponseStatus();
2985    * </p>
2986    *
2987    * <ul class='notes'>
2988    *    <li>Use the {@link RestClientBuilder#executorService(ExecutorService, boolean)} method to customize the
2989    *       executor service used for creating {@link Future Futures}.
2990    *    <li>You do not need to execute {@link InputStream#close()} on the response body to consume the response.
2991    * </ul>
2992    *
2993    * @return The HTTP status code.
2994    * @throws RestCallException If the executor service was not defined.
2995    */
2996   public Future<RestResponse> completeFuture() throws RestCallException {
2997      return client.getExecutorService().submit(
2998         new Callable<RestResponse>() {
2999            @Override /* Callable */
3000            public RestResponse call() throws Exception {
3001               return complete();
3002            }
3003         }
3004      );
3005   }
3006
3007   /**
3008    * Returns <jk>true</jk> if this request has a body.
3009    *
3010    * @return <jk>true</jk> if this request has a body.
3011    */
3012   public boolean hasHttpEntity() {
3013      return request instanceof HttpEntityEnclosingRequestBase;
3014   }
3015
3016   /**
3017    * Returns the body of this request.
3018    *
3019    * @return The body of this request, or <jk>null</jk> if it doesn't have a body.
3020    */
3021   public HttpEntity getHttpEntity() {
3022      return hasHttpEntity() ? ((HttpEntityEnclosingRequestBase)request).getEntity() : null;
3023   }
3024
3025   /**
3026    * Logs a message.
3027    *
3028    * @param level The log level.
3029    * @param t The throwable cause.
3030    * @param msg The message with {@link MessageFormat}-style arguments.
3031    * @param args The arguments.
3032    * @return This object (for method chaining).
3033    */
3034   public RestRequest log(Level level, Throwable t, String msg, Object...args) {
3035      client.log(level, t, msg, args);
3036      return this;
3037   }
3038
3039   /**
3040    * Logs a message.
3041    *
3042    * @param level The log level.
3043    * @param msg The message with {@link MessageFormat}-style arguments.
3044    * @param args The arguments.
3045    * @return This object (for method chaining).
3046    */
3047   public RestRequest log(Level level, String msg, Object...args) {
3048      client.log(level, msg, args);
3049      return this;
3050   }
3051
3052   //-----------------------------------------------------------------------------------------------------------------
3053   // HttpRequestBase pass-through methods.
3054   //-----------------------------------------------------------------------------------------------------------------
3055
3056   /**
3057    * Sets the actual request configuration.
3058    *
3059    * @param value The new value.
3060    * @return This object (for method chaining).
3061    */
3062   public RestRequest config(RequestConfig value) {
3063      request.setConfig(value);
3064      return this;
3065   }
3066
3067   /**
3068    * Sets {@link Cancellable} for the ongoing operation.
3069    *
3070    * @param cancellable The cancellable object.
3071    * @return This object (for method chaining).
3072    */
3073   public RestRequest cancellable(Cancellable cancellable) {
3074      request.setCancellable(cancellable);
3075      return this;
3076   }
3077
3078   /**
3079    * Sets the protocol version for this request.
3080    *
3081    * @param version The protocol version for this request.
3082    * @return This object (for method chaining).
3083    */
3084   public RestRequest protocolVersion(ProtocolVersion version) {
3085      request.setProtocolVersion(version);
3086      return this;
3087   }
3088
3089   /**
3090    * Used in combination with {@link #cancellable(Cancellable)}.
3091    *
3092    * @return This object (for method chaining).
3093    */
3094   public RestRequest completed() {
3095      request.completed();
3096      return this;
3097   }
3098
3099   // -----------------------------------------------------------------------------------------------------------------
3100   // HttpUriRequest pass-through methods.
3101   // -----------------------------------------------------------------------------------------------------------------
3102
3103   /**
3104    * Returns the HTTP method this request uses, such as GET, PUT, POST, or other.
3105    *
3106    * @return The HTTP method this request uses, such as GET, PUT, POST, or other.
3107    */
3108   @Override /* HttpUriRequest */
3109   public String getMethod() {
3110      return request.getMethod();
3111   }
3112
3113   /**
3114    * Returns the original request URI.
3115    *
3116    * <ul class='notes'>
3117    *    <li>URI remains unchanged in the course of request execution and is not updated if the request is redirected to another location.
3118    * </ul>
3119    *
3120    * @return The original request URI.
3121    */
3122   @Override /* HttpUriRequest */
3123   public URI getURI() {
3124      return request.getURI();
3125   }
3126
3127   /**
3128    * Returns the original request URI as a simple string.
3129    *
3130    * <ul class='notes'>
3131    *    <li>URI remains unchanged in the course of request execution and is not updated if the request is redirected to another location.
3132    * </ul>
3133    *
3134    * @return The original request URI.
3135    */
3136   public String getUri() {
3137      return getURI().toString();
3138   }
3139
3140   /**
3141    * Aborts this http request. Any active execution of this method should return immediately.
3142    *
3143    * If the request has not started, it will abort after the next execution.
3144    * <br>Aborting this request will cause all subsequent executions with this request to fail.
3145    */
3146   @Override /* HttpUriRequest */
3147   public void abort() throws UnsupportedOperationException {
3148      request.abort();
3149   }
3150
3151   @Override /* HttpUriRequest */
3152   public boolean isAborted() {
3153      return request.isAborted();
3154   }
3155
3156   /**
3157    * Returns the request line of this request.
3158    *
3159    * @return The request line.
3160    */
3161   @Override /* HttpRequest */
3162   public RequestLine getRequestLine() {
3163      return request.getRequestLine();
3164   }
3165
3166   /**
3167    * Returns the protocol version this message is compatible with.
3168    *
3169    * @return The protocol version.
3170    */
3171   @Override /* HttpMessage */
3172   public ProtocolVersion getProtocolVersion() {
3173      return request.getProtocolVersion();
3174   }
3175
3176   /**
3177    * Checks if a certain header is present in this message.
3178    *
3179    * Header values are ignored.
3180    *
3181    * @param name The header name to check for.
3182    * @return <jk>true</jk> if at least one header with this name is present.
3183    */
3184   @Override /* HttpMessage */
3185   public boolean containsHeader(String name) {
3186      return request.containsHeader(name);
3187   }
3188
3189   /**
3190    * Returns all the headers with a specified name of this message.
3191    *
3192    * Header values are ignored.
3193    * <br>Headers are ordered in the sequence they will be sent over a connection.
3194    *
3195    * @param name The name of the headers to return.
3196    * @return The headers whose name property equals name.
3197    */
3198   @Override /* HttpMessage */
3199   public Header[] getHeaders(String name) {
3200      return request.getHeaders(name);
3201   }
3202
3203   /**
3204    * Returns the first header with a specified name of this message.
3205    *
3206    * Header values are ignored.
3207    * <br>If there is more than one matching header in the message the first element of {@link #getHeaders(String)} is returned.
3208    * <br>If there is no matching header in the message <jk>null</jk> is returned.
3209    *
3210    * @param name The name of the header to return.
3211    * @return The first header whose name property equals name or <jk>null</jk> if no such header could be found.
3212    */
3213   @Override /* HttpMessage */
3214   public Header getFirstHeader(String name) {
3215      return request.getFirstHeader(name);
3216   }
3217
3218   /**
3219    * Returns the last header with a specified name of this message.
3220    *
3221    * Header values are ignored.
3222    * <br>If there is more than one matching header in the message the last element of {@link #getHeaders(String)} is returned.
3223    * <br>If there is no matching header in the message null is returned.
3224    *
3225    * @param name The name of the header to return.
3226    * @return The last header whose name property equals name or <jk>null</jk> if no such header could be found.
3227    */
3228   @Override /* HttpMessage */
3229   public Header getLastHeader(String name) {
3230      return request.getLastHeader(name);
3231   }
3232
3233   /**
3234    * Returns all the headers of this message.
3235    *
3236    * Headers are ordered in the sequence they will be sent over a connection.
3237    *
3238    * @return All the headers of this message
3239    */
3240   @Override /* HttpMessage */
3241   public Header[] getAllHeaders() {
3242      return request.getAllHeaders();
3243   }
3244
3245   /**
3246    * Adds a header to this message.
3247    *
3248    * The header will be appended to the end of the list.
3249    *
3250    * <ul class='notes'>
3251    *    <li>{@link #header(Header)} is an equivalent method and the preferred method for fluent-style coding.
3252    * </ul>
3253    *
3254    * @param header The header to append.
3255    */
3256   @Override /* HttpMessage */
3257   public void addHeader(Header header) {
3258      request.addHeader(header);
3259   }
3260
3261   /**
3262    * Adds a header to this message.
3263    *
3264    * The header will be appended to the end of the list.
3265    *
3266    * <ul class='notes'>
3267    *    <li>{@link #header(String,Object)} is an equivalent method and the preferred method for fluent-style coding.
3268    * </ul>
3269    *
3270    * @param name The name of the header.
3271    * @param value The value of the header.
3272    */
3273   @Override /* HttpMessage */
3274   public void addHeader(String name, String value) {
3275      request.addHeader(name, value);
3276   }
3277
3278   /**
3279    * Overwrites the first header with the same name.
3280    *
3281    * The new header will be appended to the end of the list, if no header with the given name can be found.
3282    *
3283    * @param header The header to set.
3284    */
3285   @Override /* HttpMessage */
3286   public void setHeader(Header header) {
3287      request.setHeader(header);
3288   }
3289
3290   /**
3291    * Overwrites the first header with the same name.
3292    *
3293    * The new header will be appended to the end of the list, if no header with the given name can be found.
3294    *
3295    * @param name The name of the header.
3296    * @param value The value of the header.
3297    */
3298   @Override /* HttpMessage */
3299   public void setHeader(String name, String value) {
3300      request.setHeader(name, value);
3301   }
3302
3303   /**
3304    * Overwrites all the headers in the message.
3305    *
3306    * @param headers The array of headers to set.
3307    */
3308   @Override /* HttpMessage */
3309   public void setHeaders(Header[] headers) {
3310      request.setHeaders(headers);
3311   }
3312
3313   /**
3314    * Removes a header from this message.
3315    *
3316    * @param header The header to remove.
3317    */
3318   @Override /* HttpMessage */
3319   public void removeHeader(Header header) {
3320      request.removeHeader(header);
3321   }
3322
3323   /**
3324    * Removes all headers with a certain name from this message.
3325    *
3326    * @param name The name of the headers to remove.
3327    */
3328   @Override /* HttpMessage */
3329   public void removeHeaders(String name) {
3330      request.removeHeaders(name);
3331   }
3332
3333   /**
3334    * Returns an iterator of all the headers.
3335    *
3336    * @return Iterator that returns {@link Header} objects in the sequence they are sent over a connection.
3337    */
3338   @Override /* HttpMessage */
3339   public HeaderIterator headerIterator() {
3340      return request.headerIterator();
3341   }
3342
3343   /**
3344    * Returns an iterator of the headers with a given name.
3345    *
3346    * @param name the name of the headers over which to iterate, or <jk>null</jk> for all headers.
3347    * @return Iterator that returns {@link Header} objects with the argument name in the sequence they are sent over a connection.
3348    */
3349   @Override /* HttpMessage */
3350   public HeaderIterator headerIterator(String name) {
3351      return request.headerIterator(name);
3352   }
3353
3354   /**
3355    * Returns the parameters effective for this message as set by {@link #setParams(HttpParams)}.
3356    *
3357    * @return The parameters effective for this message as set by {@link #setParams(HttpParams)}.
3358    * @deprecated Use constructor parameters of configuration API provided by HttpClient.
3359    */
3360   @Override /* HttpMessage */
3361   @Deprecated
3362   public HttpParams getParams() {
3363      return request.getParams();
3364   }
3365
3366   /**
3367    * Provides parameters to be used for the processing of this message.
3368    *
3369    * @param params The parameters.
3370    * @deprecated Use constructor parameters of configuration API provided by HttpClient.
3371    */
3372   @Override /* HttpMessage */
3373   @Deprecated
3374   public void setParams(HttpParams params) {
3375      request.setParams(params);
3376   }
3377
3378   /**
3379    * Returns the actual request configuration.
3380    *
3381    * @return The actual request configuration.
3382    */
3383   @Override /* Configurable */
3384   public RequestConfig getConfig() {
3385      return request.getConfig();
3386   }
3387
3388   // -----------------------------------------------------------------------------------------------------------------
3389   // Utility methods
3390   // -----------------------------------------------------------------------------------------------------------------
3391
3392   private ContentType getRequestContentType(ContentType def) {
3393      Header h = request.getFirstHeader("Content-Type");
3394      if (h != null) {
3395         String s = h.getValue();
3396         if (! isEmpty(s))
3397            return ContentType.create(s);
3398      }
3399      return def;
3400   }
3401
3402   @Override
3403   public OMap getProperties() {
3404      return super.getProperties();
3405   }
3406
3407   @SuppressWarnings("unchecked")
3408   private static Map<Object,Object> toMap(Object o) {
3409      return (Map<Object,Object>)o;
3410   }
3411
3412   private static SerializedNameValuePair serializedNameValuePair(Object key, Object value, HttpPartType type, HttpPartSerializerSession serializer, HttpPartSchema schema, EnumSet<AddFlag> flags) {
3413      return key == null ? null : new SerializedNameValuePair(stringify(key), value, type, serializer, schema, flags == null ? false : flags.contains(SKIP_IF_EMPTY));
3414   }
3415
3416   private static SerializedHeader serializedHeader(Object key, Object value, HttpPartSerializerSession serializer, HttpPartSchema schema, EnumSet<AddFlag> flags) {
3417      return key == null ? null : new SerializedHeader(stringify(key), value, serializer, schema, flags == null ? false : flags.contains(SKIP_IF_EMPTY));
3418   }
3419
3420   private static boolean isNameValuePairArray(Object o) {
3421      if (o == null || ! o.getClass().isArray())
3422         return false;
3423      if (NameValuePair.class.isAssignableFrom(o.getClass().getComponentType()))
3424         return true;
3425      return false;
3426   }
3427
3428   private static boolean isHeaderArray(Object o) {
3429      if (o == null || ! o.getClass().isArray())
3430         return false;
3431      if (Header.class.isAssignableFrom(o.getClass().getComponentType()))
3432         return true;
3433      return false;
3434   }
3435
3436   //-----------------------------------------------------------------------------------------------------------------
3437   // Other methods
3438   //-----------------------------------------------------------------------------------------------------------------
3439
3440   @Override /* Session */
3441   public OMap toMap() {
3442      return super.toMap()
3443         .a("RestCall", new DefaultFilteringOMap()
3444            .a("client", client)
3445            .a("hasInput", hasInput)
3446            .a("ignoreErrors", ignoreErrors)
3447            .a("interceptors", interceptors)
3448            .a("partSerializer", partSerializer)
3449            .a("requestBodySchema", requestBodySchema)
3450            .a("response", response)
3451            .a("serializer", serializer)
3452         );
3453   }
3454}