001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.rest.client.classic;
018
019import static java.lang.Character.isWhitespace;
020import static java.util.logging.Level.*;
021import static org.apache.juneau.commons.httppart.HttpPartType.*;
022import static org.apache.juneau.commons.lang.StateEnum.*;
023import static org.apache.juneau.commons.utils.CollectionUtils.*;
024import static org.apache.juneau.commons.utils.CollectionUtils.isEmpty;
025import static org.apache.juneau.commons.utils.Shorts.*;
026import static org.apache.juneau.commons.utils.StringUtils.*;
027import static org.apache.juneau.commons.utils.StringUtils.isEmpty;
028import static org.apache.juneau.commons.utils.ThrowableUtils.*;
029import static org.apache.juneau.http.HttpMethod.*;
030import static org.apache.juneau.http.classic.HttpEntities.*;
031import static org.apache.juneau.http.classic.HttpHeaders.*;
032import static org.apache.juneau.http.classic.HttpParts.*;
033import static org.apache.juneau.rest.RestSharedConstants.*;
034import static org.apache.juneau.rest.client.classic.RestOperation.*;
035
036import java.io.*;
037import java.lang.reflect.*;
038import java.lang.reflect.Proxy;
039import java.net.*;
040import java.nio.charset.*;
041import java.util.*;
042import java.util.concurrent.*;
043import java.util.concurrent.atomic.*;
044import java.util.function.*;
045import java.util.logging.*;
046import java.util.regex.*;
047
048import javax.net.ssl.*;
049
050import org.apache.http.*;
051import org.apache.http.NameValuePair;
052import org.apache.http.auth.*;
053import org.apache.http.client.*;
054import org.apache.http.client.CookieStore;
055import org.apache.http.client.config.*;
056import org.apache.http.client.entity.*;
057import org.apache.http.client.methods.*;
058import org.apache.http.client.utils.*;
059import org.apache.http.config.*;
060import org.apache.http.conn.*;
061import org.apache.http.conn.routing.*;
062import org.apache.http.conn.socket.*;
063import org.apache.http.conn.ssl.*;
064import org.apache.http.conn.util.*;
065import org.apache.http.cookie.*;
066import org.apache.http.impl.client.*;
067import org.apache.http.impl.conn.*;
068import org.apache.http.params.*;
069import org.apache.http.protocol.*;
070import org.apache.http.ssl.SSLContexts;
071import org.apache.juneau.commons.*;
072import org.apache.juneau.commons.collections.*;
073import org.apache.juneau.commons.function.*;
074import org.apache.juneau.commons.http.*;
075import org.apache.juneau.commons.httppart.*;
076import org.apache.juneau.commons.inject.*;
077import org.apache.juneau.commons.reflect.*;
078import org.apache.juneau.http.classic.entity.*;
079import org.apache.juneau.http.classic.header.*;
080import org.apache.juneau.http.classic.part.*;
081import org.apache.juneau.http.classic.remote.RrpcInterfaceMeta;
082import org.apache.juneau.http.classic.resource.*;
083import org.apache.juneau.http.remote.*;
084import org.apache.juneau.marshall.*;
085import org.apache.juneau.marshall.bson.*;
086import org.apache.juneau.marshall.cbor.*;
087import org.apache.juneau.marshall.hjson.*;
088import org.apache.juneau.marshall.hocon.*;
089import org.apache.juneau.marshall.html.*;
090import org.apache.juneau.marshall.httppart.*;
091import org.apache.juneau.marshall.ini.*;
092import org.apache.juneau.marshall.jcs.*;
093import org.apache.juneau.marshall.json.*;
094import org.apache.juneau.marshall.json5.*;
095import org.apache.juneau.marshall.json5l.*;
096import org.apache.juneau.marshall.jsonl.*;
097import org.apache.juneau.marshall.markdown.*;
098import org.apache.juneau.marshall.marshaller.*;
099import org.apache.juneau.marshall.marshaller.Uon;
100import org.apache.juneau.marshall.msgpack.*;
101import org.apache.juneau.marshall.oapi.*;
102import org.apache.juneau.marshall.parquet.*;
103import org.apache.juneau.marshall.parser.*;
104import org.apache.juneau.marshall.parser.ParseException;
105import org.apache.juneau.marshall.plaintext.*;
106import org.apache.juneau.marshall.prototext.*;
107import org.apache.juneau.marshall.serializer.*;
108import org.apache.juneau.marshall.toml.*;
109import org.apache.juneau.marshall.uon.*;
110import org.apache.juneau.marshall.urlencoding.*;
111import org.apache.juneau.marshall.xml.*;
112import org.apache.juneau.rest.*;
113import org.apache.juneau.rest.client.classic.assertion.*;
114import org.apache.juneau.rest.client.classic.remote.*;
115
116/**
117 * Utility class for interfacing with remote REST interfaces.
118 *
119 * <p>
120 * Built upon the feature-rich Apache HttpClient library, the Juneau RestClient API adds support for fluent-style
121 * REST calls and the ability to perform marshalling of POJOs to and from HTTP parts.
122 *
123 * <h5 class='figure'>Example:</h5>
124 * <p class='bjava'>
125 *    <jc>// Create a basic REST client with JSON support and download a bean.</jc>
126 *    MyBean <jv>bean</jv> = RestClient.<jsm>create</jsm>()
127 *       .json5()
128 *       .build()
129 *       .get(<jsf>URI</jsf>)
130 *       .run()
131 *       .assertStatus().asCode().is(200)
132 *       .assertHeader(<js>"Content-Type"</js>).matchesSimple(<js>"application/json*"</js>)
133 *       .getContent().as(MyBean.<jk>class</jk>);
134 * </p>
135 *
136 * <p>
137 * Breaking apart the fluent call, we can see the classes being used:
138 * <p class='bjava'>
139 *    RestClient.Builder&lt;?&gt; <jv>builder</jv> = RestClient.<jsm>create</jsm>().json5();
140 *    RestClient <jv>client</jv> = <jv>builder</jv>.build();
141 *    RestRequest <jv>req</jv> = <jv>client</jv>.get(<jsf>URI</jsf>);
142 *    RestResponse <jv>res</jv> = <jv>req</jv>.run();
143 *    RestResponseStatusLineAssertion <jv>statusLineAssertion</jv> = <jv>res</jv>.assertStatus();
144 *    FluentIntegerAssertion&lt;RestResponse&gt; <jv>codeAssertion</jv> = <jv>statusLineAssertion</jv>.asCode();
145 *    <jv>res</jv> = <jv>codeAssertion</jv>.is(200);
146 *    FluentStringAssertion&lt;RestResponse&gt; <jv>headerAssertion</jv> = <jv>res</jv>.assertHeader(<js>"Content-Type"</js>);
147 *    <jv>res</jv> = <jv>headerAssertion</jv>.matchesSimple(<js>"application/json*"</js>);
148 *    RestResponseBody <jv>content</jv> = <jv>res</jv>.getContent();
149 *    MyBean <jv>bean</jv> = <jv>content</jv>.as(MyBean.<jk>class</jk>);
150 * </p>
151 *
152 * <p>
153 * It additionally provides support for creating remote proxy interfaces using REST as the transport medium.
154 *
155 * <h5 class='figure'>Example:</h5>
156 * <p class='bjava'>
157 *    <jc>// Define a Remote proxy for interacting with a REST interface.</jc>
158 *    <ja>@Remote</ja>(path=<js>"/petstore"</js>)
159 *    <jk>public interface</jk> PetStore {
160 *
161 *       <ja>@RemotePost</ja>(<js>"/pets"</js>)
162 *       Pet addPet(
163 *          <ja>@Content</ja> CreatePet <jv>pet</jv>,
164 *          <ja>@Header</ja>(<js>"E-Tag"</js>) UUID <jv>etag</jv>,
165 *          <ja>@Query</ja>(<js>"debug"</js>) <jk>boolean</jk> <jv>debug</jv>
166 *       );
167 *    }
168 *
169 *    <jc>// Use a RestClient with default JSON 5 support.</jc>
170 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().json5().build();
171 *
172 *    PetStore <jv>store</jv> = <jv>client</jv>.getRemote(PetStore.<jk>class</jk>, <js>"http://localhost:10000"</js>);
173 *    CreatePet <jv>createPet</jv> = <jk>new</jk> CreatePet(<js>"Fluffy"</js>, 9.99);
174 *    Pet <jv>pet</jv> = <jv>store</jv>.addPet(<jv>createPet</jv>, UUID.<jsm>randomUUID</jsm>(), <jk>true</jk>);
175 * </p>
176 *
177 * <p>
178 * The classes are closely tied to Apache HttpClient, yet provide lots of additional functionality:
179 * <ul class='javatree'>
180 *    <li class='jc'>{@link RestClient} <jk>extends</jk> {@link HttpClient}, creates {@link RestRequest} objects.
181 *    <li class='jc'>{@link RestRequest} <jk>extends</jk> {@link HttpUriRequest}, creates {@link RestResponse} objects.
182 *    <li class='jc'>{@link RestResponse} creates {@link ResponseContent} and {@link ResponseHeader} objects.
183 *    <li class='jc'>{@link ResponseContent} <jk>extends</jk> {@link HttpEntity}
184 *    <li class='jc'>{@link ResponseHeader} <jk>extends</jk> {@link Header}
185 * </ul>
186 *
187 *
188 * <p>
189 * Instances of this class are built using the {@link Builder} class which can be constructed using
190 * the {@link #create() RestClient.create()} method as shown above.
191 *
192 * <p>
193 * Clients are typically created with a root URI so that relative URIs can be used when making requests.
194 * This is done using the {@link Builder#rootUrl(Object)} method.
195 *
196 * <h5 class='figure'>Example:</h5>
197 * <p class='bjava'>
198 *    <jc>// Create a client where all URIs are relative to localhost.</jc>
199 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().json().rootUrl(<js>"http://localhost:5000"</js>).build();
200 *
201 *    <jc>// Use relative paths.</jc>
202 *    String <jv>body</jv> = <jv>client</jv>.get(<js>"/subpath"</js>).run().getContent().asString();
203 * </p>
204 *
205 * <p>
206 * The {@link RestClient} class creates {@link RestRequest} objects using the following methods:
207 *
208 * <ul class='javatree'>
209 *    <li class='jc'>{@link RestClient}
210 *    <ul>
211 *       <li class='jm'>{@link RestClient#get(Object) get(uri)} / {@link RestClient#get() get()}
212 *       <li class='jm'>{@link RestClient#put(Object,Object) put(uri,body)} / {@link RestClient#put(Object) put(uri)}
213 *       <li class='jm'>{@link RestClient#post(Object) post(uri,body)} / {@link RestClient#post(Object) post(uri)}
214 *       <li class='jm'>{@link RestClient#patch(Object,Object) patch(uri,body)} / {@link RestClient#patch(Object) patch(uri)}
215 *       <li class='jm'>{@link RestClient#delete(Object) delete(uri)}
216 *       <li class='jm'>{@link RestClient#head(Object) head(uri)}
217 *       <li class='jm'>{@link RestClient#options(Object) options(uri)}
218 *       <li class='jm'>{@link RestClient#formPost(Object,Object) formPost(uri,body)} / {@link RestClient#formPost(Object) formPost(uri)}
219 *       <li class='jm'>{@link RestClient#formPostPairs(Object,String...) formPostPairs(uri,parameters...)}
220 *       <li class='jm'>{@link RestClient#request(String,Object,Object) request(method,uri,body)}
221 *    </ul>
222 * </ul>
223 *
224 * <p>
225 * The {@link RestRequest} class creates {@link RestResponse} objects using the following methods:
226 *
227 * <ul class='javatree'>
228 *    <li class='jc'>{@link RestRequest}
229 *    <ul>
230 *       <li class='jm'>{@link RestRequest#run() run()}
231 *       <li class='jm'>{@link RestRequest#complete() complete()}
232 *    </ul>
233 * </ul>
234 *
235 * <p>
236 * The distinction between the two methods is that {@link RestRequest#complete() complete()} automatically consumes the response body and
237 * {@link RestRequest#run() run()} does not.  Note that you must consume response bodies in order for HTTP connections to be freed up
238 * for reuse!  The {@link InputStream InputStreams} returned by the {@link ResponseContent} object are auto-closing once
239 * they are exhausted, so it is often not necessary to explicitly close them.
240 *
241 * <p>
242 * The following examples show the distinction between the two calls:
243 *
244 * <p class='bjava'>
245 *    <jc>// Consuming the response, so use run().</jc>
246 *    String <jv>body</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).run().getContent().asString();
247 *
248 *    <jc>// Only interested in response status code, so use complete().</jc>
249 *    <jk>int</jk> <jv>status</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).complete().getStatusCode();
250 * </p>
251 *
252 *
253 * <h4 class='topic'>POJO Marshalling</h4>
254 *
255 * <p>
256 * By default, JSON support is provided for HTTP request and response bodies.
257 * Other languages can be specified using any of the following builder methods:
258 * <ul class='javatree'>
259 *    <li class='jc'>{@link Builder}
260 *    <ul>
261 *       <li class='jm'>{@link Builder#json() json()}
262 *       <li class='jm'>{@link Builder#json5() json5()}
263 *       <li class='jm'>{@link Builder#xml() xml()}
264 *       <li class='jm'>{@link Builder#html() html()}
265 *       <li class='jm'>{@link Builder#plainText() plainText()}
266 *       <li class='jm'>{@link Builder#bson() bson()}
267 *       <li class='jm'>{@link Builder#msgPack() msgPack()}
268 *       <li class='jm'>{@link Builder#uon() uon()}
269 *       <li class='jm'>{@link Builder#urlEnc() urlEnc()}
270 *       <li class='jm'>{@link Builder#openApi() openApi()}
271 *    </ul>
272 * </ul>
273 *
274 * <h5 class='figure'>Example:</h5>
275 * <p class='bjava'>
276 *    <jc>// Create a basic REST client with JSON 5 support.</jc>
277 *    <jc>// Typically easier to use when performing unit tests.</jc>
278 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().json5().build();
279 * </p>
280 *
281 * <p>
282 * Clients can also support multiple languages:
283 *
284 * <h5 class='figure'>Example:</h5>
285 * <p class='bjava'>
286 *    <jc>// Create a REST client with support for multiple languages.</jc>
287 *    RestClient <jv>client1</jv> = RestClient.<jsm>create</jsm>().json().xml().openApi().build();
288 *
289 *    <jc>// Create a REST client with support for all supported languages.</jc>
290 *    RestClient <jv>client2</jv> = RestClient.<jsm>create</jsm>().universal().build();
291 * </p>
292 *
293 * <p>
294 * When using clients with multiple language support, you must specify the <c>Content-Type</c> header on requests
295 * with bodies to specify which serializer should be selected.
296 *
297 * <p class='bjava'>
298 *    <jc>// Create a REST client with support for multiple languages.</jc>
299 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().universal().build();
300 *
301 *    <jv>client</jv>
302 *       .post(<jsf>URI</jsf>, <jv>myBean</jv>)
303 *       .contentType(<js>"application/json"</js>)
304 *       .complete()
305 *       .assertStatus().is(200);
306 * </p>
307 *
308 * <p>
309 * Languages can also be specified per-request.
310 *
311 * <p class='bjava'>
312 *    <jc>// Create a REST client with no default languages supported.</jc>
313 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().build();
314 *
315 *    <jc>// Use JSON for this request.</jc>
316 *    <jv>client</jv>
317 *       .post(<jsf>URI</jsf>, <jv>myBean</jv>)
318 *       .json()
319 *       .complete()
320 *       .assertStatus().is(200);
321 * </p>
322 *
323 *
324 * <p>
325 * The {@link Builder} class provides convenience methods for setting common serializer and parser
326 * settings.
327 *
328 * <h5 class='figure'>Example:</h5>
329 * <p class='bjava'>
330 *    <jc>// Create a basic REST client with JSON support.</jc>
331 *    <jc>// Use single-quotes and whitespace.</jc>
332 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().json().sq().ws().build();
333 * </p>
334 *
335 * <p>
336 *    Other methods are also provided for specifying the serializers and parsers used for lower-level marshalling support:
337 * <ul class='javatree'>
338 *    <li class='jc'>{@link Builder}
339 *    <ul>
340 *       <li class='jm'>{@link Builder#serializer(Serializer) serializer(Serializer)}
341 *       <li class='jm'>{@link Builder#parser(Parser) parser(Parser)}
342 *       <li class='jm'>{@link Builder#marshaller(Marshaller) marshaller(Marshaller)}
343 *    </ul>
344 * </ul>
345 *
346 * <p>
347 * HTTP parts (headers, query parameters, form data...) are serialized and parsed using the {@link HttpPartSerializer}
348 * and {@link HttpPartParser} APIs.  By default, clients are configured to use {@link OpenApiSerializer} and
349 * {@link OpenApiParser}.  These can be overridden using the following methods:
350 * <ul class='javatree'>
351 *    <li class='jc'>{@link Builder}
352 *    <ul>
353 *       <li class='jm'>{@link Builder#partSerializer(Class) partSerializer(Class&lt;? extends HttpPartSerializer>)}
354 *       <li class='jm'>{@link Builder#partParser(Class) partParser(Class&lt;? extends HttpPartParser>)}
355 *    </ul>
356 * </ul>
357 *
358 *
359 * <h4 class='topic'>Request Headers</h4>
360 * <p>
361 * Per-client or per-request headers can be specified using the following methods:
362 * <ul class='javatree'>
363 *    <li class='jc'>{@link Builder}
364 *    <ul>
365 *       <li class='jm'>{@link Builder#headers() headerData()}
366 *       <li class='jm'>{@link Builder#header(String,String) header(String,Object)}
367 *       <li class='jm'>{@link Builder#header(String,Supplier) header(String,Supplier&lt;?&gt;)}
368 *       <li class='jm'>{@link Builder#headers(Header...) headers(Header...)}
369 *       <li class='jm'>{@link Builder#headersDefault(Header...) defaultHeaders(Header...)}
370 *    </ul>
371 *    <li class='jc'>{@link RestRequest}
372 *    <ul>
373 *       <li class='jm'>{@link RestRequest#header(String,Object) header(String,Object)}
374 *       <li class='jm'>{@link RestRequest#headers(Header...) headers(Header...)}
375 *       <li class='jm'>{@link RestRequest#headersBean(Object) headersBean(Object)}
376 *       <li class='jm'>{@link RestRequest#headerPairs(String...) headerPairs(String...)}
377 *    </ul>
378 * </ul>
379 *
380 * <p>
381 * The supplier methods are particularly useful for header values whose values may change over time (such as <c>Authorization</c> headers
382 * which may need to change every few minutes).
383 * </p>
384 *
385 * <h5 class='figure'>Example:</h5>
386 * <p class='bjava'>
387 *    <jc>// Create a client that adds a dynamic Authorization header to every request.</jc>
388 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().header(<js>"Authorization"</js>, ()-&gt;getMyAuthToken()).build();
389 * </p>
390 *
391 * <p>
392 * The {@link HttpPartSchema} API allows you to define OpenAPI schemas to POJO data structures on both requests
393 * and responses.
394 *
395 * <h5 class='figure'>Example:</h5>
396 * <p class='bjava'>
397 *    <jc>// Create a client that adds a header "Foo: bar|baz" to every request.</jc>
398 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>()
399 *       .header(<js>"Foo"</js>, AList.<jsm>of</jsm>(<js>"bar"</js>,<js>"baz"</js>), <jsf>T_ARRAY_PIPES</jsf>)
400 *       .build();
401 * </p>
402 *
403 * <p>
404 * The methods with {@link ListOperation} parameters allow you to control whether new headers get appended, prepended, or
405 * replace existing headers with the same name.
406 *
407 * <h5 class='section'>Notes:</h5><ul>
408 *    <li class='note'>Methods that pass in POJOs convert values to strings using the part serializers.  Methods that pass in <c>Header</c> or
409 *       <c>NameValuePair</c> objects use the values returned by that bean directly.
410 * </ul>
411 *
412 *
413 * <h4 class='topic'>Request Query Parameters</h4>
414 * <p>
415 * Per-client or per-request query parameters can be specified using the following methods:
416 * <ul class='javatree'>
417 *    <li class='jc'>{@link Builder}
418 *    <ul>
419 *       <li class='jm'>{@link Builder#queryData() queryData()}
420 *       <li class='jm'>{@link Builder#queryData(String,String) queryData(String,String)}
421 *       <li class='jm'>{@link Builder#queryData(String,Supplier) queryData(String,Supplier&lt;?&gt;)}
422 *       <li class='jm'>{@link Builder#queryData(NameValuePair...) queryData(NameValuePair...)}
423 *       <li class='jm'>{@link Builder#queryDataDefault(NameValuePair...) defaultQueryData(NameValuePair...)}
424 *    </ul>
425 *    <li class='jc'>{@link RestRequest}
426 *    <ul>
427 *       <li class='jm'>{@link RestRequest#queryData(String,Object) queryData(String,Object)}
428 *       <li class='jm'>{@link RestRequest#queryData(NameValuePair...) queryData(NameValuePair...)}
429 *       <li class='jm'>{@link RestRequest#queryDataBean(Object) queryDataBean(Object)}
430 *       <li class='jm'>{@link RestRequest#queryCustom(Object) queryCustom(Object)}
431 *       <li class='jm'>{@link RestRequest#queryDataPairs(String...) queryDataPairs(String...)}
432 *    </ul>
433 * </ul>
434 *
435 * <h5 class='figure'>Example:</h5>
436 * <p class='bjava'>
437 *    <jc>// Create a client that adds a ?foo=bar query parameter to every request.</jc>
438 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().query(<js>"foo"</js>, <js>"bar"</js>).build();
439 *
440 *    <jc>// Or do it on every request.</jc>
441 *    String <jv>response</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).query(<js>"foo"</js>, <js>"bar"</js>).run().getContent().asString();
442 * </p>
443 *
444 * <h5 class='section'>Notes:</h5><ul>
445 *    <li class='note'>Like header values, dynamic values and OpenAPI schemas are supported.
446 *    <li class='note'>Methods that pass in POJOs convert values to strings using the part serializers.  Methods that pass in <c>NameValuePair</c>
447 *       objects use the values returned by that bean directly.
448 * </ul>
449 *
450 *
451 * <h4 class='topic'>Request Form Data</h4>
452 *
453 * <p>
454 * Per-client or per-request form-data parameters can be specified using the following methods:
455 * <ul class='javatree'>
456 *    <li class='jc'>{@link Builder}
457 *    <ul>
458 *       <li class='jm'>{@link Builder#formData() formData()}
459 *       <li class='jm'>{@link Builder#formData(String,String) formData(String,String)}
460 *       <li class='jm'>{@link Builder#formData(String,Supplier) formData(String,Supplier&lt;?&gt;)}
461 *       <li class='jm'>{@link Builder#formData(NameValuePair...) formDatas(NameValuePair...)}
462 *       <li class='jm'>{@link Builder#formDataDefault(NameValuePair...) defaultFormData(NameValuePair...)}
463 *    </ul>
464 *    <li class='jc'>{@link RestRequest}
465 *    <ul>
466 *       <li class='jm'>{@link RestRequest#formData(String,Object) formData(String,Object)}
467 *       <li class='jm'>{@link RestRequest#formData(NameValuePair...) formData(NameValuePair...)}
468 *       <li class='jm'>{@link RestRequest#formDataBean(Object) formDataBean(Object)}
469 *       <li class='jm'>{@link RestRequest#formDataCustom(Object) formDataCustom(Object)}
470 *       <li class='jm'>{@link RestRequest#formDataPairs(String...) formDataPairs(String...)}
471 *    </ul>
472 * </ul>
473 *
474 * <h5 class='section'>Notes:</h5><ul>
475 *    <li class='note'>Like header values, dynamic values and OpenAPI schemas are supported.
476 *    <li class='note'>Methods that pass in POJOs convert values to strings using the part serializers.  Methods that pass in <c>NameValuePair</c>
477 *       objects use the values returned by that bean directly.
478 * </ul>
479 *
480 *
481 * <h4 class='topic'>Request Body</h4>
482 *
483 * <p>
484 * The request body can either be passed in with the client creator method (e.g. {@link RestClient#post(Object,Object) post(uri,body)}),
485 * or can be specified via the following methods:
486 *
487 * <ul class='javatree'>
488 *    <li class='jc'>{@link RestRequest}
489 *    <ul>
490 *       <li class='jm'>{@link RestRequest#content(Object) body(Object)}
491 *       <li class='jm'>{@link RestRequest#content(Object,HttpPartSchema) body(Object,HttpPartSchema)}
492 *    </ul>
493 * </ul>
494 *
495 * <p>
496 * The request body can be any of the following types:
497 * <ul class='javatree'>
498 *       <li class='jc'>
499 *          {@link Object} - POJO to be converted to text using the {@link Serializer} defined on the client or request.
500 *       <li class='jc'>
501 *          {@link Reader} - Raw contents of {@code Reader} will be serialized to remote resource.
502 *       <li class='jc'>
503 *          {@link InputStream} - Raw contents of {@code InputStream} will be serialized to remote resource.
504 *       <li class='jc'>
505 *          {@link HttpResource} - Raw contents will be serialized to remote resource.  Additional headers and media type will be set on request.
506 *       <li class='jc'>
507 *          {@link HttpEntity} - Bypass Juneau serialization and pass HttpEntity directly to HttpClient.
508 *       <li class='jc'>
509 *          {@link PartList} - Converted to a URL-encoded FORM post.
510 *       <li class='jc'>
511 *          {@link Supplier} - A supplier of anything on this list.
512 *    </ul>
513 *
514 * <h5 class='section'>Notes:</h5><ul>
515 *    <li class='note'>If the serializer on the client or request is explicitly set to <jk>null</jk>, POJOs will be converted to strings
516 *       using the registered part serializer as content type <js>"text/plain</js>.  If the part serializer is also <jk>null</jk>,
517 *       POJOs will be converted to strings using {@link ClassMeta#toString(Object)} which typically just calls {@link Object#toString()}.
518 * </ul>
519 *
520 *
521 * <h4 class='topic'>Response Status</h4>
522 *
523 * <p>
524 * After execution using {@link RestRequest#run()} or {@link RestRequest#complete()}, the following methods can be used
525 * to get the response status:
526 *
527 * <ul class='javatree'>
528 *    <li class='jc'>{@link RestResponse}
529 *    <ul>
530 *       <li class='jm'><c>{@link RestResponse#getStatusLine() getStatusLine()} <jk>returns</jk> {@link StatusLine}</c>
531 *       <li class='jm'><c>{@link RestResponse#getStatusCode() getStatusCode()} <jk>returns</jk> <jk>int</jk></c>
532 *       <li class='jm'><c>{@link RestResponse#getReasonPhrase() getReasonPhrase()} <jk>returns</jk> String</c>
533 *       <li class='jm'><c>{@link RestResponse#assertStatus() assertStatus()} <jk>returns</jk> {@link FluentResponseStatusLineAssertion}</c>
534 *    </ul>
535 * </ul>
536 *
537 * <h5 class='figure'>Example:</h5>
538 * <p class='bjava'>
539 *    <jc>// Only interested in status code.</jc>
540 *    <jk>int</jk> <jv>statusCode</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).complete().getStatusCode();
541 * </p>
542 *
543 * <p>
544 * Equivalent methods with mutable parameters are provided to allow access to status values without breaking fluent call chains.
545 *
546 * <h5 class='figure'>Example:</h5>
547 * <p class='bjava'>
548 *    <jc>// Interested in multiple values.</jc>
549 *    Holder&lt;Integer&gt; <jv>statusCode</jv> = Holder.<jsm>create</jsm>();
550 *    Holder&lt;String&gt; <jv>reasonPhrase</jv> = Holder.<jsm>create</jsm>();
551 *
552 *    <jv>client</jv>.get(<jsf>URI</jsf>).complete().getStatusCode(<jv>statusCode</jv>).getReasonPhrase(<jv>reasonPhrase</jv>);
553 *    System.<jsf>err</jsf>.println(<js>"statusCode="</js>+<jv>statusCode</jv>.get()+<js>", reasonPhrase="</js>+<jv>reasonPhrase</jv>.get());
554 * </p>
555 *
556 * <h5 class='section'>Notes:</h5><ul>
557 *    <li class='note'>If you are only interested in the response status and not the response body, be sure to use {@link RestRequest#complete()} instead
558 *       of {@link RestRequest#run()} to make sure the response body gets automatically cleaned up.  Otherwise you must
559 *       consume the response yourself.
560 * </ul>
561 *
562 * <p>
563 * The assertion method is provided for quickly asserting status codes in fluent calls.
564 *
565 * <h5 class='figure'>Example:</h5>
566 * <p class='bjava'>
567 *    <jc>// Status assertion using a static value.</jc>
568 *    String <jv>body</jv> = <jv>client</jv>.get(<jsf>URI</jsf>)
569 *       .run()
570 *       .assertStatus().asCode().isBetween(200,399)
571 *       .getContent().asString();
572 *
573 *    <jc>// Status assertion using a predicate.</jc>
574 *    String <jv>body</jv> = <jv>client</jv>.get(<jsf>URI</jsf>)
575 *       .run()
576 *       .assertStatus().asCode().is(<jv>x</jv> -&gt; <jv>x</jv>&lt;400)
577 *       .getContent().asString();
578 * </p>
579 *
580 *
581 * <h4 class='topic'>Response Headers</h4>
582 *
583 * <p>
584 * Response headers are accessed through the following methods:
585 *
586 * <ul class='javatree'>
587 *    <li class='jc'>{@link RestResponse}
588 *    <ul>
589 *       <li class='jm'><c>{@link RestResponse#getHeaders(String) getHeaders(String)} <jk>returns</jk> {@link ResponseHeader}[]</c>
590 *       <li class='jm'><c>{@link RestResponse#getFirstHeader(String) getFirstHeader(String)} <jk>returns</jk> {@link ResponseHeader}</c>
591 *       <li class='jm'><c>{@link RestResponse#getLastHeader(String) getLastHeader(String)} <jk>returns</jk> {@link ResponseHeader}</c>
592 *       <li class='jm'><c>{@link RestResponse#getAllHeaders() getAllHeaders()} <jk>returns</jk> {@link ResponseHeader}[]</c>
593 *       <li class='jm'><c>{@link RestResponse#getStringHeader(String) getStringHeader(String)} <jk>returns</jk> String</c>
594 *       <li class='jm'><c>{@link RestResponse#containsHeader(String) containsHeader(String)} <jk>returns</jk> <jk>boolean</jk></c>
595 *    </ul>
596 * </ul>
597 *
598 * <p>
599 * The {@link RestResponse#getFirstHeader(String)} and {@link RestResponse#getLastHeader(String)} methods return an empty {@link ResponseHeader} object instead of<jk>null</jk>.
600 * This allows it to be used more easily in fluent calls.
601 *
602 * <h5 class='figure'>Example:</h5>
603 * <p class='bjava'>
604 *    <jc>// See if response contains Location header.</jc>
605 *    <jk>boolean</jk> <jv>hasLocationHeader</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).complete().getLastHeader(<js>"Location"</js>).exists();
606 * </p>
607 *
608 * <p>
609 * The {@link ResponseHeader} class extends from the HttpClient {@link Header} class and provides several convenience
610 * methods:
611 *
612 * <ul class='javatree'>
613 *    <li class='jc'>{@link ResponseHeader}
614 *    <ul>
615 *       <li class='jm'><c>{@link ResponseHeader#isPresent() isPresent()} <jk>returns</jk> <jk>boolean</jk></c>
616 *       <li class='jm'><c>{@link ResponseHeader#asString() asString()} <jk>returns</jk> String</c>
617 *       <li class='jm'><c>{@link ResponseHeader#as(Type,Type...) as(Type,Type...)} <jk>returns</jk> T</c>
618 *       <li class='jm'><c>{@link ResponseHeader#as(Class) as(Class&lt;T&gt;)} <jk>returns</jk> T</c>
619 *       <li class='jm'><c>{@link ResponseHeader#asMatcher(Pattern) asMatcher(Pattern)} <jk>returns</jk> {@link Matcher}</c>
620 *       <li class='jm'><c>{@link ResponseHeader#asMatcher(String) asMatcher(String)} <jk>returns</jk> {@link Matcher}</c>
621 *       <li class='jm'><c>{@link ResponseHeader#asHeader(Class) asHeader(Class&lt;T <jk>extends</jk> BasicHeader&gt; c)} <jk>returns</jk> {@link BasicHeader}</c>
622 *       <li class='jm'><c>{@link ResponseHeader#asStringHeader() asStringHeader()} <jk>returns</jk> {@link BasicStringHeader}</c>
623 *       <li class='jm'><c>{@link ResponseHeader#asIntegerHeader() asIntegerHeader()} <jk>returns</jk> {@link BasicIntegerHeader}</c>
624 *       <li class='jm'><c>{@link ResponseHeader#asLongHeader() asLongHeader()} <jk>returns</jk> {@link BasicLongHeader}</c>
625 *       <li class='jm'><c>{@link ResponseHeader#asDateHeader() asDateHeader()} <jk>returns</jk> {@link BasicDateHeader}</c>
626 *       <li class='jm'><c>{@link ResponseHeader#asCsvHeader() asCsvHeader()} <jk>returns</jk> {@link BasicCsvHeader}</c>
627 *       <li class='jm'><c>{@link ResponseHeader#asEntityTagsHeader() asEntityTagsHeader()} <jk>returns</jk> {@link BasicEntityTagsHeader}</c>
628 *       <li class='jm'><c>{@link ResponseHeader#asStringRangesHeader() asStringRangesHeader()} <jk>returns</jk> {@link BasicStringRangesHeader}</c>
629 *       <li class='jm'><c>{@link ResponseHeader#asUriHeader() asUriHeader()} <jk>returns</jk> {@link BasicUriHeader}</c>
630 *    </ul>
631 * </ul>
632 *
633 * <p>
634 * The {@link ResponseHeader#schema(HttpPartSchema)} method allows you to perform parsing of OpenAPI formats for
635 * header parts.
636 *
637 * <h5 class='figure'>Example:</h5>
638 * <p class='bjava'>
639 *    <jc>// Parse the header "Foo: bar|baz".</jc>
640 *    List&lt;String&gt; <jv>fooHeader</jv> = <jv>client</jv>
641 *       .get(<jsf>URI</jsf>)
642 *       .complete()
643 *       .getHeader(<js>"Foo"</js>).schema(<jsf>T_ARRAY_PIPES</jsf>).as(List.<jk>class</jk>, String.<jk>class</jk>);
644 * </p>
645 *
646 * <p>
647 * Assertion methods are also provided for fluent-style calls:
648 *
649 * <ul class='javatree'>
650 *    <li class='jc'>{@link ResponseHeader}
651 *    <ul>
652 *       <li class='jm'><c>{@link ResponseHeader#assertValue() assertValue()} <jk>returns</jk> {@link FluentResponseHeaderAssertion}</c>
653 *    </ul>
654 * </ul>
655 *
656 * <p>
657 * Note how in the following example, the fluent assertion returns control to the {@link RestResponse} object after
658 * the assertion has been completed:
659 *
660 * <h5 class='figure'>Example:</h5>
661 * <p class='bjava'>
662 *    <jc>// Assert the response content type is any sort of JSON.</jc>
663 *    String <jv>body</jv> = <jv>client</jv>.get(<jsf>URI</jsf>)
664 *       .run()
665 *       .getHeader(<js>"Content-Type"</js>).assertValue().matchesSimple(<js>"application/json*"</js>)
666 *       .getContent().asString();
667 * </p>
668 *
669 *
670 * <h4 class='topic'>Response Body</h4>
671 *
672 * <p>
673 * The response body is accessed through the following method:
674 *
675 * <ul class='javatree'>
676 *    <li class='jc'>{@link RestResponse}
677 *    <ul>
678 *       <li class='jm'><c>{@link RestResponse#getContent() getContent()} <jk>returns</jk> {@link ResponseContent}</c>
679 *    </ul>
680 * </ul>
681 *
682 * <p>
683 * The {@link ResponseContent} class extends from the HttpClient {@link HttpEntity} class and provides several convenience
684 * methods:
685 *
686 * <ul class='javatree'>
687 *    <li class='jc'>{@link ResponseContent}
688 *    <ul>
689 *       <li class='jm'><c>{@link ResponseContent#asInputStream() asInputStream()} <jk>returns</jk> InputStream</c>
690 *       <li class='jm'><c>{@link ResponseContent#asReader() asReader()} <jk>returns</jk> Reader</c>
691 *       <li class='jm'><c>{@link ResponseContent#asReader(Charset) asReader(Charset)} <jk>returns</jk> Reader</c>
692 *       <li class='jm'><c>{@link ResponseContent#pipeTo(OutputStream) pipeTo(OutputStream)} <jk>returns</jk> {@link RestResponse}</c>
693 *       <li class='jm'><c>{@link ResponseContent#pipeTo(Writer) pipeTo(Writer)} <jk>returns</jk> {@link RestResponse}</c>
694 *       <li class='jm'><c>{@link ResponseContent#as(Type,Type...) as(Type,Type...)} <jk>returns</jk> T</c>
695 *       <li class='jm'><c>{@link ResponseContent#as(Class) as(Class&lt;T&gt;)} <jk>returns</jk> T</c>
696 *       <li class='jm'><c>{@link ResponseContent#asFuture(Class) asFuture(Class&lt;T&gt;)} <jk>returns</jk> Future&lt;T&gt;</c>
697 *       <li class='jm'><c>{@link ResponseContent#asFuture(Type,Type...) asFuture(Type,Type...)} <jk>returns</jk> Future&lt;T&gt;</c>
698 *       <li class='jm'><c>{@link ResponseContent#asString() asString()} <jk>returns</jk> String</c>
699 *       <li class='jm'><c>{@link ResponseContent#asStringFuture() asStringFuture()} <jk>returns</jk> Future&lt;String&gt;</c>
700 *       <li class='jm'><c>{@link ResponseContent#asAbbreviatedString(int) asAbbreviatedString(int)} <jk>returns</jk> String</c>
701 *       <li class='jm'><c>{@link ResponseContent#asMatcher(Pattern) asMatcher(Pattern)} <jk>returns</jk> {@link Matcher}</c>
702 *       <li class='jm'><c>{@link ResponseContent#asMatcher(String) asMatcher(String)} <jk>returns</jk> {@link Matcher}</c>
703 *    </ul>
704 * </ul>
705 *
706 * <br>
707 *
708 * <h5 class='figure'>Examples:</h5>
709 * <p class='bjava'>
710 *    <jc>// Parse into a linked-list of strings.</jc>
711 *    List&lt;String&gt; <jv>list1</jv> = <jv>client</jv>
712 *       .get(<jsf>URI</jsf>)
713 *       .run()
714 *       .getContent().as(LinkedList.<jk>class</jk>, String.<jk>class</jk>);
715 *
716 *    <jc>// Parse into a linked-list of beans.</jc>
717 *    List&lt;MyBean&gt; <jv>list2</jv> = <jv>client</jv>
718 *       .get(<jsf>URI</jsf>)
719 *       .run()
720 *       .getContent().as(LinkedList.<jk>class</jk>, MyBean.<jk>class</jk>);
721 *
722 *    <jc>// Parse into a linked-list of linked-lists of strings.</jc>
723 *    List&lt;List&lt;String&gt;&gt; <jv>list3</jv> = <jv>client</jv>
724 *       .get(<jsf>URI</jsf>)
725 *       .run()
726 *       .getContent().as(LinkedList.<jk>class</jk>, LinkedList.<jk>class</jk>, String.<jk>class</jk>);
727 *
728 *    <jc>// Parse into a map of string keys/values.</jc>
729 *    Map&lt;String,String&gt; <jv>map1</jv> = <jv>client</jv>
730 *       .get(<jsf>URI</jsf>)
731 *       .run()
732 *       .getContent().as(TreeMap.<jk>class</jk>, String.<jk>class</jk>, String.<jk>class</jk>);
733 *
734 *    <jc>// Parse into a map containing string keys and values of lists containing beans.</jc>
735 *    Map&lt;String,List&lt;MyBean&gt;&gt; <jv>map2</jv> = <jv>client</jv>
736 *       .get(<jsf>URI</jsf>)
737 *       .run()
738 *       .getContent().as(TreeMap.<jk>class</jk>, String.<jk>class</jk>, List.<jk>class</jk>, MyBean.<jk>class</jk>);
739 * </p>
740 *
741 * <p>
742 * The response body can only be consumed once unless it has been cached into memory.  In many cases, the body is
743 * automatically cached when using the assertions methods or methods such as {@link ResponseContent#asString()}.
744 * However, methods that involve reading directly from the input stream cannot be called twice.
745 * In these cases, the {@link RestResponse#cacheContent()} and {@link ResponseContent#cache()} methods are provided
746 * to cache the response body in memory so that you can perform several operations against it.
747 *
748 * <p class='bjava'>
749 *    <jc>// Cache the response body so we can access it twice.</jc>
750 *    InputStream <jv>inputStream</jv> = <jv>client</jv>
751 *       .get(<jsf>URI</jsf>)
752 *       .run()
753 *       .cacheBody()
754 *       .getContent().pipeTo(<jv>someOtherStream</jv>)
755 *       .getContent().asInputStream();
756 * </p>
757 *
758 * <p>
759 * Assertion methods are also provided for fluent-style calls:
760 *
761 * <ul class='javatree'>
762 *    <li class='jc'>{@link ResponseContent}
763 *    <ul>
764 *       <li class='jm'><c>{@link ResponseContent#assertValue() assertValue()} <jk>returns</jk> {@link FluentResponseBodyAssertion}</c>
765 *    </ul>
766 * </ul>
767 *
768 * <br>
769 *
770 * <h5 class='figure'>Example:</h5>
771 * <p class='bjava'>
772 *    <jc>// Assert that the body contains the string "Success".</jc>
773 *    String <jv>body</jv> = <jv>client</jv>
774 *       .get(<jsf>URI</jsf>)
775 *       .run()
776 *       .getContent().assertString().contains(<js>"Success"</js>)
777 *       .getContent().asString();
778 * </p>
779 *
780 * <p>
781 * Object assertions allow you to parse the response body into a POJO and then perform various tests on that resulting
782 * POJO.
783 *
784 * <h5 class='figure'>Example:</h5>
785 * <p class='bjava'>
786 *    <jc>// Parse bean into POJO and then validate that it was parsed correctly.</jc>
787 *    MyBean <jv>bean</jv> = <jv>client</jv>.get(<jsf>URI</jsf>)
788 *       .run()
789 *       .getContent().assertObject(MyBean.<jk>class</jk>).asJson().is(<js>"{foo:'bar'}"</js>)
790 *       .getContent().as(MyBean.<jk>class</jk>);
791 * </p>
792 *
793 *
794 * <h4 class='topic'>Custom Call Handlers</h4>
795 *
796 * <p>
797 * The {@link RestCallHandler} interface provides the ability to provide custom handling of requests.
798 *
799 * <ul class='javatree'>
800 *    <li class='jc'>{@link Builder}
801 *    <ul>
802 *       <li class='jm'>{@link Builder#callHandler() callHandler()}
803 *    </ul>
804 *    <li class='jic'>{@link RestCallHandler}
805 *    <ul>
806 *       <li class='jm'><c>{@link RestCallHandler#run(HttpHost,HttpRequest,HttpContext) run(HttpHost,HttpRequest,HttpContext)} <jk>returns</jk> HttpResponse</c>
807 *    </ul>
808 * </ul>
809 *
810 * <p>
811 * Note that there are other ways of accomplishing this such as extending the {@link RestClient} class and overriding
812 * the {@link #run(HttpHost,HttpRequest,HttpContext)} method
813 * or by defining your own {@link HttpRequestExecutor}.  Using this interface is often simpler though.
814 *
815 *
816 * <h4 class='topic'>Interceptors</h4>
817 *
818 * <p>
819 * The {@link RestCallInterceptor} API provides a quick way of intercepting and manipulating requests and responses beyond
820 * the existing {@link HttpRequestInterceptor} and {@link HttpResponseInterceptor} APIs.
821 *
822 * <ul class='javatree'>
823 *    <li class='jc'>{@link Builder}
824 *    <ul>
825 *       <li class='jm'>{@link Builder#interceptors(Object...) interceptors(Object...)}
826 *    </ul>
827 *    <li class='jc'>{@link RestRequest}
828 *    <ul>
829 *       <li class='jm'>{@link RestRequest#interceptors(RestCallInterceptor...) interceptors(RestCallInterceptor...)}
830 *    </ul>
831 *    <li class='jic'>{@link RestCallInterceptor}
832 *    <ul>
833 *       <li class='jm'>{@link RestCallInterceptor#onInit(RestRequest) onInit(RestRequest)}
834 *       <li class='jm'>{@link RestCallInterceptor#onConnect(RestRequest,RestResponse) onConnect(RestRequest,RestResponse)}
835 *       <li class='jm'>{@link RestCallInterceptor#onClose(RestRequest,RestResponse) onClose(RestRequest,RestResponse)}
836 *    </ul>
837 * </ul>
838 *
839 *
840 * <h4 class='topic'>Logging / Debugging</h4>
841 *
842 * <p>
843 * The following methods provide logging of requests and responses:
844 *
845 * <ul class='javatree'>
846 *    <li class='jc'>{@link Builder}
847 *    <ul>
848 *       <li class='jm'>{@link Builder#logger(Logger) logger(Logger)}
849 *       <li class='jm'>{@link Builder#logToConsole() logToConsole()}
850 *       <li class='jm'>{@link Builder#logRequests(DetailLevel,Level,BiPredicate) logRequests(DetailLevel,Level,BiPredicate)}
851 *    </ul>
852 * </ul>
853 *
854 * <p>
855 * The following example shows the results of logging all requests that end with <c>/bean</c>.
856 *
857 * <h5 class='figure'>Examples:</h5>
858 * <p class='bjava'>
859 *    MyBean <jv>bean</jv> = RestClient
860 *       .<jsm>create</jsm>()
861 *       .json5()
862 *       .logRequests(DetailLevel.<jsf>FULL</jsf>, Level.<jsf>SEVERE</jsf>, (<jv>req</jv>,<jv>res</jv>)-&gt;<jv>req</jv>.getUri().endsWith(<js>"/bean"</js>))
863 *       .logToConsole()
864 *       .build()
865 *       .post(<js>"http://localhost/bean"</js>, <jv>anotherBean</jv>)
866 *       .run()
867 *       .getContent().as(MyBean.<jk>class</jk>);
868 * </p>
869 *
870 * <p>
871 * This produces the following console output:
872 *
873 * <p class='bconsole'>
874 *    === HTTP Call (outgoing) ======================================================
875 *    === REQUEST ===
876 *    POST http://localhost/bean
877 *    ---request headers---
878 *       Accept: application/json5
879 *    ---request entity---
880 *    Content-Type: application/json5
881 *    ---request content---
882 *    {f:1}
883 *    === RESPONSE ===
884 *    HTTP/1.1 200
885 *    ---response headers---
886 *       Content-Type: application/json
887 *    ---response content---
888 *    {f:1}
889 *    === END =======================================================================",
890 * </p>
891 *
892 *
893 * <p class='notes'>
894 * It should be noted that if you enable request logging detail level {@link DetailLevel#FULL}, response bodies will be cached by default which may introduce
895 * a performance penalty.
896 *
897 * <p>
898 * Additionally, the following method is also provided for enabling debug mode:
899 *
900 * <ul class='javatree'>
901 *    <li class='jc'>{@link Builder}
902 *    <ul>
903 *       <li class='jm'>{@link Builder#debug() debug()}
904 *    </ul>
905 * </ul>
906 *
907 * <p>
908 * Enabling debug mode has the following effects:
909 * <ul>
910 *    <li>{@link org.apache.juneau.marshall.Context.Builder#debug() Context.Builder#debug()} is enabled.
911 *    <li>{@link Builder#detectLeaks()} is enabled.
912 *    <li>{@link Builder#logToConsole()} is called.
913 * </ul>
914 *
915 *
916 * <h4 class='topic'>REST Proxies</h4>
917 *
918 * <p>
919 * One of the more powerful features of the REST client class is the ability to produce Java interface proxies against
920 * arbitrary remote REST resources.
921 *
922 * <h5 class='figure'>Example:</h5>
923 * <p class='bjava'>
924 *    <jc>// Define a Remote proxy for interacting with a REST interface.</jc>
925 *    <ja>@Remote</ja>(path=<js>"/petstore"</js>)
926 *    <jk>public interface</jk> PetStore {
927 *
928 *       <ja>@RemotePost</ja>(<js>"/pets"</js>)
929 *       Pet addPet(
930 *          <ja>@Content</ja> CreatePet <jv>pet</jv>,
931 *          <ja>@Header</ja>(<js>"E-Tag"</js>) UUID <jv>etag</jv>,
932 *          <ja>@Query</ja>(<js>"debug"</js>) <jk>boolean</jk> <jv>debug</jv>
933 *       );
934 *    }
935 *
936 *    <jc>// Use a RestClient with default JSON 5 support.</jc>
937 *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().json5().build())
938 *
939 *    PetStore <jv>store</jv> = <jv>client</jv>.getRemote(PetStore.<jk>class</jk>, <js>"http://localhost:10000"</js>);
940 *    CreatePet <jv>createPet</jv> = <jk>new</jk> CreatePet(<js>"Fluffy"</js>, 9.99);
941 *    Pet <jv>pet</jv> = <jv>store</jv>.addPet(<jv>createPet</jv>, UUID.<jsm>randomUUID</jsm>(), <jk>true</jk>);
942 * </p>
943 *
944 * <p>
945 * The methods to retrieve remote interfaces are:
946 *
947 * <ul class='javatree'>
948 *    <li class='jc'>{@link RestClient}
949 *    <ul>
950 *       <li class='jm'><c>{@link RestClient#getRemote(Class) getRemote(Class&lt;T&gt;)} <jk>returns</jk> T</c>
951 *       <li class='jm'><c>{@link RestClient#getRemote(Class,Object) getRemote(Class&lt;T&gt;,Object)} <jk>returns</jk> T</c>
952 *       <li class='jm'><c>{@link RestClient#getRemote(Class,Object,Serializer,Parser) getRemote(Class&lt;T&gt;,Object,Serializer,Parser)} <jk>returns</jk> T</c>
953 *       <li class='jm'><c>{@link RestClient#getRrpcInterface(Class) getRrpcInterface(Class&lt;T&gt;)} <jk>returns</jk> T</c>
954 *       <li class='jm'><c>{@link RestClient#getRrpcInterface(Class,Object) getRrpcInterface(Class&lt;T&gt;,Object)} <jk>returns</jk> T</c>
955 *       <li class='jm'><c>{@link RestClient#getRrpcInterface(Class,Object,Serializer,Parser) getRrpcInterface(Class&lt;T&gt;,Object,Serializer,Parser)} <jk>returns</jk> T</c>
956 *    </ul>
957 * </ul>
958 *
959 * <p>
960 * Two basic types of remote interfaces are provided:
961 *
962 * <ul class='spaced-list'>
963 *    <li>{@link Remote @Remote}-annotated interfaces.  These can be defined against arbitrary external REST resources.
964 *    <li>RPC-over-REST interfaces.  These are Java interfaces that allow you to make method calls on server-side POJOs.
965 * </ul>
966 *
967 * <p>
968 * Refer to the following documentation on both flavors:
969 *
970 * <ul class='doctree'>
971 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestProxies">REST Proxies</a>
972 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestRpc">REST/RPC</a>
973 * </ul>
974 *
975 * <br>
976 * <hr>
977 * <h4 class='topic'>Customizing Apache HttpClient</h4>
978 *
979 * <p>
980 * Several methods are provided for customizing the underlying HTTP client and client builder classes:
981 * <ul class='javatree'>
982 *    <li class='jc'>{@link Builder}
983 *    <ul>
984 *       <li class='jm'>{@link Builder#httpClientBuilder(HttpClientBuilder) httpClientBuilder(HttpClientBuilder)} - Set the client builder yourself.
985 *       <li class='jm'>{@link Builder#createHttpClientBuilder() createHttpClientBuilder()} - Override to create the client builder.
986 *       <li class='jm'>{@link Builder#createHttpClient() createHttpClient()} - Override to create the client.
987 *       <li class='jm'>{@link Builder#createConnectionManager() createConnectionManager()} - Override to create the connection management.
988 *    </ul>
989 * </ul>
990 *
991 * <p>
992 * Additionally, all methods on the <c>HttpClientBuilder</c> class have been extended with fluent setters.
993 *
994 * <h5 class='figure'>Example:</h5>
995 * <p class='bjava'>
996 *    <jc>// Create a client with customized HttpClient settings.</jc>
997 *    MyBean <jv>bean</jv> = RestClient
998 *       .<jsm>create</jsm>()
999 *       .disableRedirectHandling()
1000 *       .connectionManager(<jv>myConnectionManager</jv>)
1001 *       .addInterceptorFirst(<jv>myHttpRequestInterceptor</jv>)
1002 *       .build();
1003 * </p>
1004 *
1005 * <p>
1006 * Refer to the {@link HttpClientBuilder HTTP Client Builder API} for more information.
1007 *
1008 *
1009 * <h4 class='topic'>Extending RestClient</h4>
1010 *
1011 * <p>
1012 * The <c>RestClient</c> API has been designed to allow for the ability to be easily extended.
1013 * The following example that overrides the primary run method shows how this can be done.
1014 *
1015 * <h5 class='figure'>Example:</h5>
1016 * <p class='bjava'>
1017 *    <jk>public class</jk> MyRestClient <jk>extends</jk> RestClient {
1018 *
1019 *       <jc>// Must provide this constructor!</jc>
1020 *       <jk>public</jk> MyRestClient(RestClient.Builder&lt;?&gt; <jv>builder</jv>) {
1021 *          <jk>super</jk>(<jv>builder</jv>);
1022 *       }
1023 *
1024 *       <jd>/** Optionally override to customize builder settings before initialization. </jd>
1025 *       <ja>@Override</ja>
1026 *       <jk>protected void</jk> init(RestClient.Builder&lt;?&gt;) {...}
1027 *
1028 *       <jd>/** Optionally override to provide post-initialization (e.g. setting up SAML handshakes, etc...). </jd>
1029 *       <ja>@Override</ja>
1030 *       <jk>protected void</jk> init() {...}
1031 *
1032 *       <jd>/** Optionally override to customize requests when they're created (e.g. add headers to each request). </jd>
1033 *       <ja>@Override</ja>
1034 *       <jk>protected</jk> RestRequest request(RestOperation) {...}
1035 *
1036 *       <jd>/** Optionally override to implement your own call handling. </jd>
1037 *       <ja>@Override</ja>
1038 *       <jk>protected</jk> HttpResponse run(HttpHost, HttpRequest, HttpContext) {...}
1039 *
1040 *       <jd>/** Optionally override to customize requests before they're executed. </jd>
1041 *       <ja>@Override</ja>
1042 *       <jk>protected void</jk> onCallInit(RestRequest) {...}
1043 *
1044 *       <jd>/** Optionally override to customize responses as soon as a connection is made. </jd>
1045 *       <ja>@Override</ja>
1046 *       <jk>protected void</jk> onCallConnect(RestRequest, RestResponse) {...}
1047 *
1048 *       <jd>/** Optionally override to perform any call cleanup. </jd>
1049 *       <ja>@Override</ja>
1050 *       <jk>protected void</jk> onCallClose(RestRequest, RestResponse) {...}
1051 *    }
1052 *
1053 *    <jc>// Instantiate your client.</jc>
1054 *    MyRestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().json().build(MyRestClient.<jk>class</jk>);
1055 * </p>
1056 *
1057 * <p>
1058 * The {@link RestRequest} and {@link RestResponse} objects can also be extended and integrated by overriding the
1059 * {@link RestClient#createRequest(URI,String,boolean)} and {@link RestClient#createResponse(RestRequest,HttpResponse,Parser)} methods.
1060 *
1061 * <h5 class='section'>Notes:</h5><ul>
1062 *    <li class='note'>This class is thread safe and reusable.
1063 * </ul>
1064 *
1065 * <h5 class='section'>See Also:</h5><ul>
1066 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauRestClient">juneau-rest-client-classic</a>
1067 * </ul>
1068 */
1069@SuppressWarnings({
1070   "java:S106", // System.err is the intentional default fallback for the configurable console PrintStream
1071   "java:S112", // Builder.interceptors(Class...), executeRemoteWithRetry(), materializeRemote() and throwRemoteError() declare throws Exception because remote-proxy calls surface arbitrary checked exceptions
1072   "java:S115", // Constants use UPPER_snakeCase naming convention
1073   "java:S1133", // Deprecated override required by HttpClient interface
1074   "java:S1192", // Duplicated literals (argument/property names) read more clearly inline than as constants
1075   "java:S3776", // buildRemoteRequest(), executeRemoteWithRetry(), callback() and getRrpcInterface() are branch-heavy remote-call orchestration; splitting them would obscure the flow
1076   "java:S6539", // Monster class; RestClient is intentionally a single fluent builder/client aggregating config, call orchestration, and remote-proxy wiring
1077   "rawtypes", // Raw types necessary for generic type handling.
1078   "resource", // Resource management handled externally
1079   "unchecked" // Casts in getInstance() (Class<? extends Serializer/Parser>) and in the getRemote()/getRrpcInterface() Proxy.newProxyInstance results are guarded by isAssignableFrom checks and the proxied interface type
1080})
1081public class RestClient extends MarshallingContextable implements HttpClient, Closeable {
1082
1083   // Argument name constants for reqnn
1084   private static final String HEADER_ACCEPT = org.apache.juneau.http.header.Accept.NAME;
1085   private static final String HEADER_CONTENT_TYPE = org.apache.juneau.http.header.ContentType.NAME;
1086
1087   /**
1088    * Builder class.
1089    */
1090   @SuppressWarnings({
1091      "java:S119" // 'SELF' (CRTP self-type) is intentional and clearer than a single-letter name.
1092   })
1093   public abstract static class Builder<SELF extends Builder<SELF>> extends MarshallingContextable.Builder<SELF> {
1094
1095      private BeanInstantiator.Builder<RestCallHandler> callHandler;
1096      private final WritableBeanStore beanStore = new BasicBeanStore();
1097      private BiPredicate<RestRequest,RestResponse> logRequestsPredicate;
1098      private boolean detectLeaks;
1099      private boolean allowPrivateUrls;
1100      private final List<String> allowedAddressRanges = new ArrayList<>();
1101      private boolean executorServiceShutdownOnClose;
1102      private boolean ignoreErrors;
1103      private boolean keepHttpClientOpen;
1104      private boolean logToConsole;
1105      private boolean pooled;
1106      private boolean skipEmptyFormData;
1107      private boolean skipEmptyHeaderData;
1108      private boolean skipEmptyQueryData;
1109      private CloseableHttpClient httpClient;
1110      private DetailLevel logRequests;
1111      private ExecutorService executorService;
1112      private HeaderList headerData;
1113      private HttpClientBuilder httpClientBuilder;
1114      private HttpClientConnectionManager connectionManager;
1115      // The instance the default createConnectionManager() last returned; only that one can be given a pinned twin.
1116      private HttpClientConnectionManager defaultConnectionManager;
1117      // The socket-factory registry and pool settings of defaultConnectionManager, which its pinned twin shares.
1118      private Registry<ConnectionSocketFactory> defaultRegistry;
1119      private PoolSettings defaultPoolSettings;
1120      // TLS and pool settings, applied to both pools of the connection manager the default createConnectionManager()
1121      // builds (HttpClientBuilder ignores its own copies once a connection manager is set).
1122      private HostnameVerifier sslHostnameVerifier;
1123      private LayeredConnectionSocketFactory sslSocketFactory;
1124      private SSLContext sslContext;
1125      private int maxConnPerRoute;
1126      private int maxConnTotal;
1127      private ConnectionConfig defaultConnectionConfig;
1128      private SocketConfig defaultSocketConfig;
1129      private PublicSuffixMatcher publicSuffixMatcher;
1130      private long connTimeToLive;
1131      private TimeUnit connTimeToLiveTimeUnit;
1132      private boolean systemProperties;
1133      // Set by the default createHttpClient() to the two-pool router it installed for SSRF-guard-active @Remote calls.
1134      private SsrfGuardConnectionManager ssrfGuard;
1135      // Set by the default createHttpClient(): whether the default createConnectionManager() (not an override, which may
1136      // hand the same instance to several clients) created both of ssrfGuard's pools, which no caller can then reach,
1137      // so the client shuts them down on close() even when the connection manager is shared.
1138      private boolean ownsConnectionManager;
1139      private HttpPartParser.Creator partParser;
1140      private HttpPartSerializer.Creator partSerializer;
1141      private Level logRequestsLevel;
1142      private Logger logger;
1143      private PartList formData;
1144      private PartList pathData;
1145      private PartList queryData;
1146      private ParserSet.Builder parsers;
1147      private Predicate<Integer> errorCodes = x -> x <= 0 || x >= 400;
1148      private PrintStream console;
1149      private SerializerSet.Builder serializers;
1150      private Supplier<String> rootUrl;
1151      private UrlEncodingSerializer.Builder urlEncodingSerializer;
1152      List<RestCallInterceptor> interceptors;
1153
1154      /**
1155       * Constructor.
1156       */
1157      protected Builder() {}
1158
1159      /**
1160       * Appends an <c>Accept</c> header on this request.
1161       *
1162       * <p>
1163       * This is a shortcut for calling <c>headerData().append(Accept.<jsm>of</jsm>(<jv>value</jv>))</c>.
1164       *
1165       * @param value
1166       *    The new header value.
1167       *    <br>Can be <jk>null</jk> (no Accept header will be added).
1168       * @return This object.
1169       * @see #headers()
1170       */
1171      public SELF accept(String value) {
1172         return headers(Accept.of(value));
1173      }
1174
1175      /**
1176       * Sets the value for the <c>Accept-Charset</c> request header on all requests.
1177       *
1178       * <p>
1179       * This is a shortcut for calling <c>headerData().append(AcceptCharset.<jsm>of</jsm>(<jv>value</jv>))</c>.
1180       *
1181       * @param value The new header value.
1182       *    <br>Can be <jk>null</jk> (no Accept-Charset header will be added).
1183       * @return This object.
1184       * @see #headers()
1185       */
1186      public SELF acceptCharset(String value) {
1187         return headers(AcceptCharset.of(value));
1188      }
1189
1190      /**
1191       * <i><l>Serializer</l> configuration property:&emsp;</i>  Add <js>"_type"</js> properties when needed.
1192       *
1193       * <p>
1194       * When enabled, <js>"_type"</js> properties will be added to beans if their type cannot be inferred
1195       * through reflection.
1196       *
1197       * <p>
1198       * This is used to recreate the correct objects during parsing if the object types cannot be inferred.
1199       * <br>For example, when serializing a <c>Map&lt;String,Object&gt;</c> field where the bean class cannot be determined from
1200       * the type of the values.
1201       *
1202       * <p>
1203       * Note the differences between the following settings:
1204       * <ul class='javatree'>
1205       *    <li class='jf'>{@link #addRootType()} - Affects whether <js>'_type'</js> is added to root node.
1206       *    <li class='jf'>{@link #addBeanTypes()} - Affects whether <js>'_type'</js> is added to any nodes.
1207       * </ul>
1208       *
1209       * <h5 class='section'>Example:</h5>
1210       * <p class='bjava'>
1211       *    <jc>// Create a JSON client that adds _type to nodes in the request body.</jc>
1212       *    RestClient <jv>client</jv> = RestClient
1213       *       .<jsm>create</jsm>()
1214       *       .json()
1215       *       .addBeanTypes()
1216       *       .build();
1217       *
1218       *    <jc>// Our map of beans to serialize.</jc>
1219       *    <ja>@Marshalled</ja>(typeName=<js>"mybean"</js>)
1220       *    <jk>public class</jk> MyBean {
1221       *       <jk>public</jk> String <jf>foo</jf> = <js>"bar"</js>;
1222       *    }
1223       *
1224       *    AMap <jv>map</jv> = AMap.of(<js>"foo"</js>, <jk>new</jk> MyBean());
1225       *
1226       *    <jc>// Request body will contain:  {"foo":{"_type":"mybean","foo":"bar"}}</jc>
1227       *    <jv>client</jv>
1228       *       .post(<js>"http://localhost:10000/foo"</js>, <jv>map</jv>)
1229       *       .run();
1230       * </p>
1231       *
1232       * <h5 class='section'>See Also:</h5><ul>
1233       *    <li class='jm'>{@link org.apache.juneau.marshall.serializer.Serializer.Builder#addBeanTypes() Serializer.Builder#addBeanTypes()}
1234       * </ul>
1235       *
1236       * @return This object.
1237       */
1238      public SELF addBeanTypes() {
1239         serializers().forEach(Serializer.Builder::addBeanTypes);
1240         return self();
1241      }
1242
1243      /**
1244       * Adds this protocol interceptor to the head of the protocol processing list.
1245       *
1246       * <h5 class='section'>Notes:</h5><ul>
1247       *    <li class='note'>This value can be overridden by the {@link #httpProcessor(HttpProcessor)} method.
1248       * </ul>
1249       *
1250       * @param itcp New property value.
1251       *    <br>Cannot be <jk>null</jk>.
1252       * @return This object.
1253       * @see HttpClientBuilder#addInterceptorFirst(HttpRequestInterceptor)
1254       */
1255      public SELF addInterceptorFirst(HttpRequestInterceptor itcp) {
1256         httpClientBuilder().addInterceptorFirst(reqnn("itcp", itcp));
1257         return self();
1258      }
1259
1260      /**
1261       * Adds this protocol interceptor to the head of the protocol processing list.
1262       *
1263       * <h5 class='section'>Notes:</h5><ul>
1264       *    <li class='note'>This value can be overridden by the {@link #httpProcessor(HttpProcessor)} method.
1265       * </ul>
1266       *
1267       * @param itcp New property value.
1268       *    <br>Cannot be <jk>null</jk>.
1269       * @return This object.
1270       * @see HttpClientBuilder#addInterceptorFirst(HttpResponseInterceptor)
1271       */
1272      public SELF addInterceptorFirst(HttpResponseInterceptor itcp) {
1273         httpClientBuilder().addInterceptorFirst(reqnn("itcp", itcp));
1274         return self();
1275      }
1276
1277      /**
1278       * Adds this protocol interceptor to the tail of the protocol processing list.
1279       *
1280       * <h5 class='section'>Notes:</h5><ul>
1281       *    <li class='note'>This value can be overridden by the {@link #httpProcessor(HttpProcessor)} method.
1282       * </ul>
1283       *
1284       * @param itcp New property value.
1285       *    <br>Cannot be <jk>null</jk>.
1286       * @return This object.
1287       * @see HttpClientBuilder#addInterceptorLast(HttpRequestInterceptor)
1288       */
1289      public SELF addInterceptorLast(HttpRequestInterceptor itcp) {
1290         httpClientBuilder().addInterceptorLast(reqnn("itcp", itcp));
1291         return self();
1292      }
1293
1294      /**
1295       * Adds this protocol interceptor to the tail of the protocol processing list.
1296       *
1297       * <h5 class='section'>Notes:</h5><ul>
1298       *    <li class='note'>This value can be overridden by the {@link #httpProcessor(HttpProcessor)} method.
1299       * </ul>
1300       *
1301       * @param itcp New property value.
1302       *    <br>Cannot be <jk>null</jk>.
1303       * @return This object.
1304       * @see HttpClientBuilder#addInterceptorLast(HttpResponseInterceptor)
1305       */
1306      public SELF addInterceptorLast(HttpResponseInterceptor itcp) {
1307         httpClientBuilder().addInterceptorLast(reqnn("itcp", itcp));
1308         return self();
1309      }
1310
1311      /**
1312       * <i><l>Serializer</l> configuration property:&emsp;</i>  Add type attribute to root nodes.
1313       *
1314       * <p>
1315       * When enabled, <js>"_type"</js> properties will be added to top-level beans.
1316       *
1317       * <p>
1318       * When disabled, it is assumed that the parser knows the exact Java POJO type being parsed, and therefore top-level
1319       * type information that might normally be included to determine the data type will not be serialized.
1320       *
1321       * <p>
1322       * For example, when serializing a top-level POJO with a {@link Marshalled#typeName() @Marshalled(typeName)} value, a
1323       * <js>'_type'</js> attribute will only be added when this setting is enabled.
1324       *
1325       * <p>
1326       * Note the differences between the following settings:
1327       * <ul class='javatree'>
1328       *    <li class='jf'>{@link #addRootType()} - Affects whether <js>'_type'</js> is added to root node.
1329       *    <li class='jf'>{@link #addBeanTypes()} - Affects whether <js>'_type'</js> is added to any nodes.
1330       * </ul>
1331       *
1332       * <h5 class='section'>Example:</h5>
1333       * <p class='bjava'>
1334       *    <jc>// Create a JSON client that adds _type to root node.</jc>
1335       *    RestClient <jv>client</jv> = RestClient
1336       *       .<jsm>create</jsm>()
1337       *       .json()
1338       *       .addRootType()
1339       *       .build();
1340       *
1341       *    <jc>// Our bean to serialize.</jc>
1342       *    <ja>@Marshalled</ja>(typeName=<js>"mybean"</js>)
1343       *    <jk>public class</jk> MyBean {
1344       *       <jk>public</jk> String <jf>foo</jf> = <js>"bar"</js>;
1345       *    }
1346       *
1347       *    <jc>// Request body will contain:  {"_type":"mybean","foo":"bar"}</jc>
1348       *    <jv>client</jv>
1349       *       .post(<js>"http://localhost:10000/foo"</js>, <jk>new</jk> MyBean())
1350       *       .run();
1351       * </p>
1352       *
1353       * <h5 class='section'>See Also:</h5><ul>
1354       *    <li class='jm'>{@link org.apache.juneau.marshall.serializer.Serializer.Builder#addRootType() Serializer.Builder#addRootType()}
1355       * </ul>
1356       *
1357       * @return This object.
1358       */
1359      public SELF addRootType() {
1360         serializers().forEach(Serializer.Builder::addRootType);
1361         return self();
1362      }
1363
1364      /**
1365       * Assigns {@link BackoffManager} instance.
1366       *
1367       * @param backoffManager New property value.
1368       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
1369       * @return This object.
1370       * @see HttpClientBuilder#setBackoffManager(BackoffManager)
1371       */
1372      public SELF backoffManager(BackoffManager backoffManager) {
1373         httpClientBuilder().setBackoffManager(backoffManager);
1374         return self();
1375      }
1376
1377      /**
1378       * Set up this client to use BASIC auth.
1379       *
1380       * <h5 class='section'>Example:</h5>
1381       * <p class='bjava'>
1382       *    <jc>// Construct a client that uses BASIC authentication.</jc>
1383       *    RestClient <jv>client</jv> = RestClient
1384       *       .<jsm>create</jsm>()
1385       *       .basicAuth(<js>"http://localhost"</js>, 80, <js>"me"</js>, <js>"mypassword"</js>)
1386       *       .build();
1387       * </p>
1388       *
1389       * @param host The auth scope hostname.
1390       *    <br>Can be <jk>null</jk> (will use <js>"*"</js> as the hostname).
1391       * @param port The auth scope port.
1392       * @param user The username.
1393       *    <br>Can be <jk>null</jk> (will use empty string).
1394       * @param pw The password.
1395       *    <br>Can be <jk>null</jk> (will use empty string).
1396       * @return This object.
1397       */
1398      public SELF basicAuth(String host, int port, String user, String pw) {
1399         var scope = new AuthScope(host, port);
1400         var up = new UsernamePasswordCredentials(user, pw);
1401         var p = new BasicCredentialsProvider();
1402         p.setCredentials(scope, up);
1403         defaultCredentialsProvider(p);
1404         return self();
1405      }
1406
1407      @Override /* Overridden from Context.Builder<?> */
1408      public RestClient build() {
1409         // Validated here, ahead of the reflective construction, so a bad entry surfaces as the IllegalArgumentException itself.
1410         RemoteUrlPolicy.AllowedRanges.of(allowedAddressRanges.toArray(new String[0]));
1411         return build(RestClient.class);
1412      }
1413
1414      /**
1415       * Returns the creator for the rest call handler.
1416       *
1417       * <p>
1418       * Allows you to provide a custom handler for making HTTP calls.
1419       *
1420       * <h5 class='section'>Example:</h5>
1421       * <p class='bjava'>
1422       *    <jc>// Create a client that handles processing of requests using a custom handler.</jc>
1423       *    <jk>public class</jk> MyRestCallHandler <jk>implements</jk> RestCallHandler {
1424       *
1425       *       <ja>@Override</ja>
1426       *       <jk>public</jk> HttpResponse run(HttpHost <jv>target</jv>, HttpRequest <jv>request</jv>, HttpContext <jv>context</jv>) <jk>throws</jk> IOException {
1427       *          <jc>// Custom handle requests.</jc>
1428       *       }
1429       *    }
1430       *
1431       *    RestClient <jv>client</jv> = RestClient
1432       *       .<jsm>create</jsm>()
1433       *       .callHandler(MyRestCallHandler.<jk>class</jk>)
1434       *       .build();
1435       * </p>
1436       *
1437       * <h5 class='section'>Notes:</h5><ul>
1438       *    <li class='warn'>The SSRF guard of {@code @Remote} calls travels on the request's {@link HttpContext}, and a
1439       *       custom handler may copy the request, or send it with another context, without it.  So a client with any handler other than
1440       *       {@link BasicRestCallHandler} itself, or with a {@code BasicRestCallHandler} bound to a different client
1441       *       (through {@code impl(...)}), refuses every SSRF-guard-active {@code @Remote} call (one without the
1442       *       {@link #allowPrivateUrls(boolean) allowPrivateUrls} opt-in).  Ordinary requests are unaffected.
1443       *    <li class='note'>
1444       *       The {@link RestClient#run(HttpHost, HttpRequest, HttpContext)} method can also be overridden to produce the same results.
1445       *       The same SSRF restriction applies: a client whose class overrides that method or either
1446       *       {@code execute(...)} overload it dispatches to refuses SSRF-guard-active {@code @Remote} calls too.
1447       *    <li class='note'>
1448       *       Use {@link org.apache.juneau.commons.inject.BeanInstantiator.Builder BeanInstantiator.Builder} <c>impl(Object)</c> to specify an already instantiated instance.
1449       *    <li class='note'>
1450       *       Use {@link org.apache.juneau.commons.inject.BeanInstantiator.Builder BeanInstantiator.Builder} <c>type(Class)</c> to specify a subtype to instantiate.
1451       *       <br>Subclass must have a public constructor that takes in any args available
1452       *       in the bean store of this builder (including {@link RestClient} itself).
1453       * </ul>
1454       *
1455       * <h5 class='section'>See Also:</h5><ul>
1456       *    <li class='jic'>{@link RestCallHandler}
1457       * </ul>
1458       *
1459       * @return The instantiator for the rest call handler.
1460       */
1461      public final BeanInstantiator.Builder<RestCallHandler> callHandler() {
1462         if (callHandler == null)
1463            callHandler = createCallHandler();
1464         return callHandler;
1465      }
1466
1467      /**
1468       * REST call handler class.
1469       *
1470       * <p>
1471       * Specifies a custom handler for making HTTP calls.
1472       *
1473       * <p>
1474       * This is a shortcut for <c>callHandler().type(<jv>value</jv>)</c>.
1475       *
1476       * @param value
1477       *    The new value for this setting.
1478       *    <br>Cannot be <jk>null</jk>.
1479       * @return This object.
1480       * @see #callHandler()
1481       */
1482      public SELF callHandler(Class<? extends RestCallHandler> value) {
1483         callHandler().type(reqnn("value", value));
1484         return self();
1485      }
1486
1487      /**
1488       * Sets the client version by setting the value for the <js>"Client-Version"</js> header.
1489       *
1490       * <p>
1491       * This is a shortcut for calling <c>headerData().append(ClientVersion.<jsm>of</jsm>(<jv>value</jv>))</c>.
1492       *
1493       * @param value The version string (e.g. <js>"1.2.3"</js>)
1494       *    <br>Can be <jk>null</jk> (no Client-Version header will be added).
1495       * @return This object.
1496       * @see #headers()
1497       */
1498      public SELF clientVersion(String value) {
1499         return headers(ClientVersion.of(value));
1500      }
1501
1502      /**
1503       * Assigns {@link ConnectionBackoffStrategy} instance.
1504       *
1505       * @param connectionBackoffStrategy New property value.
1506       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
1507       * @return This object.
1508       * @see HttpClientBuilder#setConnectionBackoffStrategy(ConnectionBackoffStrategy)
1509       */
1510      public SELF connectionBackoffStrategy(ConnectionBackoffStrategy connectionBackoffStrategy) {
1511         httpClientBuilder().setConnectionBackoffStrategy(connectionBackoffStrategy);
1512         return self();
1513      }
1514
1515      /**
1516       * Assigns {@link HttpClientConnectionManager} instance.
1517       *
1518       * <h5 class='section'>Notes:</h5><ul>
1519       *    <li class='warn'>This client cannot pin the connections of a connection manager it did not create, so a
1520       *       client built with one refuses every SSRF-guard-active {@code @Remote} call (one without the
1521       *       {@link #allowPrivateUrls(boolean) allowPrivateUrls} opt-in).  Ordinary requests are unaffected.
1522       * </ul>
1523       *
1524       * @param value New property value.
1525       *    <br>Can be <jk>null</jk> (value will not be set, a default connection manager will be created).
1526       * @return This object.
1527       * @see HttpClientBuilder#setConnectionManager(HttpClientConnectionManager)
1528       */
1529      public SELF connectionManager(HttpClientConnectionManager value) {
1530         connectionManager = value;
1531         httpClientBuilder().setConnectionManager(value);
1532         return self();
1533      }
1534
1535      /**
1536       * Defines the connection manager is to be shared by multiple client instances.
1537       *
1538       * <h5 class='section'>Notes:</h5><ul>
1539       *    <li class='note'>If the connection manager is shared its life-cycle is expected to be managed by the caller and it will not be shut down if the client is closed.
1540       *       This applies to a connection manager supplied through {@link #connectionManager(HttpClientConnectionManager)}
1541       *       or returned by an overridden {@link #createConnectionManager()} (even one that calls {@code super}, since the
1542       *       override may hand the same instance to several clients).  The connection manager the default
1543       *       {@link #createConnectionManager()} builds for a client cannot be reached by the caller, so it is never
1544       *       shared: {@link RestClient#close()} shuts it down.
1545       *    <li class='note'>The client's internal pool for SSRF-guard-active {@code @Remote} calls (see {@link #createConnectionManager()})
1546       *       is never shared, and {@link RestClient#close()} still shuts it down.  Combined with {@link #keepHttpClientOpen()},
1547       *       though, nothing shuts that internal pool (or the default connection manager) down; their connections stay
1548       *       open until they are closed as idle or the JVM exits.
1549       * </ul>
1550       *
1551       * @param shared New property value.
1552       * @return This object.
1553       * @see HttpClientBuilder#setConnectionManagerShared(boolean)
1554       */
1555      public SELF connectionManagerShared(boolean shared) {
1556         httpClientBuilder().setConnectionManagerShared(shared);
1557         return self();
1558      }
1559
1560      /**
1561       * Assigns {@link ConnectionReuseStrategy} instance.
1562       *
1563       * @param reuseStrategy New property value.
1564       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
1565       * @return This object.
1566       * @see HttpClientBuilder#setConnectionReuseStrategy(ConnectionReuseStrategy)
1567       */
1568      public SELF connectionReuseStrategy(ConnectionReuseStrategy reuseStrategy) {
1569         httpClientBuilder().setConnectionReuseStrategy(reuseStrategy);
1570         return self();
1571      }
1572
1573      /**
1574       * Sets maximum time to live for persistent connections.
1575       *
1576       * <h5 class='section'>Notes:</h5><ul>
1577       *    <li class='note'>It is applied to both pools of the connection manager the default {@link #createConnectionManager()}
1578       *       builds.  It has no effect on a connection manager supplied through
1579       *       {@link #connectionManager(HttpClientConnectionManager)} or an overridden {@link #createConnectionManager()}.
1580       *    <li class='note'>A positive value makes that connection manager a {@link PoolingHttpClientConnectionManager}, as
1581       *       {@link #pooled()} does: {@link BasicHttpClientConnectionManager} has no time-to-live.
1582       * </ul>
1583       *
1584       * @param connTimeToLive New property value.
1585       * @param connTimeToLiveTimeUnit New property value.
1586       *    <br>Cannot be <jk>null</jk>.
1587       * @return This object.
1588       * @see HttpClientBuilder#setConnectionTimeToLive(long,TimeUnit)
1589       */
1590      public SELF connectionTimeToLive(long connTimeToLive, TimeUnit connTimeToLiveTimeUnit) {
1591         this.connTimeToLive = connTimeToLive;
1592         this.connTimeToLiveTimeUnit = connTimeToLiveTimeUnit;
1593         httpClientBuilder().setConnectionTimeToLive(connTimeToLive, connTimeToLiveTimeUnit);
1594         return self();
1595      }
1596
1597      /**
1598       * Console print stream
1599       *
1600       * <p>
1601       * Allows you to redirect the console output to a different print stream.
1602       *
1603       * @param value
1604       *    The new value for this setting.
1605       *    <br>Can be <jk>null</jk> (defaults to <c>System.err</c>).
1606       * @return This object.
1607       */
1608      public SELF console(PrintStream value) {
1609         console = value;
1610         return self();
1611      }
1612
1613      /**
1614       * Assigns a map of {@link org.apache.http.client.entity.InputStreamFactory InputStreamFactories} to be used for automatic content decompression.
1615       *
1616       * @param contentDecoderMap New property value.
1617       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
1618       * @return This object.
1619       * @see HttpClientBuilder#setContentDecoderRegistry(Map)
1620       */
1621      public SELF contentDecoderRegistry(Map<String,InputStreamFactory> contentDecoderMap) {
1622         httpClientBuilder().setContentDecoderRegistry(contentDecoderMap);
1623         return self();
1624      }
1625
1626      /**
1627       * Sets the value for the <c>Content-Type</c> request header on all requests.
1628       *
1629       * <p>
1630       * This is a shortcut for calling <c>headerData().append(ContentType.<jsm>of</jsm>(<jv>value</jv>))</c>.
1631       *
1632       * <p>
1633       * This overrides the media type specified on the serializer.
1634       *
1635       * @param value The new header value.
1636       *    <br>Can be <jk>null</jk> (no Content-Type header will be added).
1637       * @return This object.
1638       * @see #headers()
1639       */
1640      public SELF contentType(String value) {
1641         return headers(ContentType.of(value));
1642      }
1643
1644      @Override /* Overridden from Context.Builder<?> */
1645      public SELF copy() {
1646         throw new NoSuchMethodError("Not implemented.");
1647      }
1648
1649      /**
1650       * Sets the value for the <c>Debug</c> request header on all requests.
1651       *
1652       * <p>
1653       * This is a shortcut for calling <c>headerData().append(Debug.<jsm>of</jsm>(<jv>value</jv>))</c>.
1654       *
1655       * @return This object.
1656       * @see #headers()
1657       */
1658      @Override
1659      public SELF debug() {
1660         super.debug();
1661         serializers().forEach(Serializer.Builder::debug);
1662         return headers(Debug.TRUE);
1663      }
1664
1665      /**
1666       * <i><l>Parser</l> configuration property:&emsp;</i>  Debug output lines.
1667       *
1668       * <p>
1669       * When parse errors occur, this specifies the number of lines of input before and after the
1670       * error location to be printed as part of the exception message.
1671       *
1672       * <h5 class='section'>Example:</h5>
1673       * <p class='bjava'>
1674       *    <jc>// Create a parser whose exceptions print out 100 lines before and after the parse error location.</jc>
1675       *    RestClient <jv>client</jv> = RestClient
1676       *       .<jsm>create</jsm>()
1677       *       .json()
1678       *       .debug()  <jc>// Enable debug mode to capture Reader contents as strings.</jc>
1679       *       .debugOuputLines(100)
1680       *       .build();
1681       *
1682       *    <jc>// Try to parse some bad JSON.</jc>
1683       *    <jk>try</jk> {
1684       *       <jv>client</jv>
1685       *          .get(<js>"/pathToBadJson"</js>)
1686       *          .run()
1687       *          .getContent().as(Object.<jk>class</jk>);  <jc>// Try to parse it.</jc>
1688       *    } <jk>catch</jk> (RestCallException <jv>e</jv>) {
1689       *       System.<jsf>err</jsf>.println(<jv>e</jv>.getMessage());  <jc>// Will display 200 lines of the output.</jc>
1690       *    }
1691       * </p>
1692       *
1693       * <h5 class='section'>See Also:</h5><ul>
1694       *    <li class='jm'>{@link org.apache.juneau.marshall.parser.Parser.Builder#debugOutputLines(int) Parser.Builder#debugOutputLines(int)}
1695       * </ul>
1696       *
1697       * @param value
1698       *    The new value for this property.
1699       *    <br>The default value is <c>5</c>.
1700       * @return This object.
1701       */
1702      public SELF debugOutputLines(int value) {
1703         parsers().forEach(x -> x.debugOutputLines(value));
1704         return self();
1705      }
1706
1707      /**
1708       * Assigns default {@link org.apache.http.auth.AuthScheme} registry which will be used for request execution if not explicitly set in the client execution context.
1709       *
1710       * @param authSchemeRegistry New property value.
1711       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
1712       * @return This object.
1713       * @see HttpClientBuilder#setDefaultAuthSchemeRegistry(Lookup)
1714       */
1715      public SELF defaultAuthSchemeRegistry(Lookup<AuthSchemeProvider> authSchemeRegistry) {
1716         httpClientBuilder().setDefaultAuthSchemeRegistry(authSchemeRegistry);
1717         return self();
1718      }
1719
1720      /**
1721       * Assigns default {@link ConnectionConfig}.
1722       *
1723       * <h5 class='section'>Notes:</h5><ul>
1724       *    <li class='note'>It is applied to both pools of the connection manager the default {@link #createConnectionManager()}
1725       *       builds.  It has no effect on a connection manager supplied through
1726       *       {@link #connectionManager(HttpClientConnectionManager)} or an overridden {@link #createConnectionManager()}.
1727       * </ul>
1728       *
1729       * @param config New property value.
1730       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
1731       * @return This object.
1732       * @see HttpClientBuilder#setDefaultConnectionConfig(ConnectionConfig)
1733       */
1734      public SELF defaultConnectionConfig(ConnectionConfig config) {
1735         this.defaultConnectionConfig = config;
1736         httpClientBuilder().setDefaultConnectionConfig(config);
1737         return self();
1738      }
1739
1740      /**
1741       * Assigns default {@link CookieSpec} registry which will be used for request execution if not explicitly set in the client execution context.
1742       *
1743       * @param cookieSpecRegistry New property value.
1744       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
1745       * @return This object.
1746       * @see HttpClientBuilder#setDefaultCookieSpecRegistry(Lookup)
1747       */
1748      public SELF defaultCookieSpecRegistry(Lookup<CookieSpecProvider> cookieSpecRegistry) {
1749         httpClientBuilder().setDefaultCookieSpecRegistry(cookieSpecRegistry);
1750         return self();
1751      }
1752
1753      /**
1754       * Assigns default {@link CookieStore} instance which will be used for request execution if not explicitly set in the client execution context.
1755       *
1756       * @param cookieStore New property value.
1757       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
1758       * @return This object.
1759       * @see HttpClientBuilder#setDefaultCookieStore(CookieStore)
1760       */
1761      public SELF defaultCookieStore(CookieStore cookieStore) {
1762         httpClientBuilder().setDefaultCookieStore(cookieStore);
1763         return self();
1764      }
1765
1766      /**
1767       * Assigns default {@link CredentialsProvider} instance which will be used for request execution if not explicitly set in the client execution context.
1768       *
1769       * @param credentialsProvider New property value.
1770       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
1771       * @return This object.
1772       * @see HttpClientBuilder#setDefaultCredentialsProvider(CredentialsProvider)
1773       */
1774      public SELF defaultCredentialsProvider(CredentialsProvider credentialsProvider) {
1775         httpClientBuilder().setDefaultCredentialsProvider(credentialsProvider);
1776         return self();
1777      }
1778
1779      /**
1780       * Assigns default {@link RequestConfig} instance which will be used for request execution if not explicitly set in the client execution context.
1781       *
1782       * @param config New property value.
1783       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
1784       * @return This object.
1785       * @see HttpClientBuilder#setDefaultRequestConfig(RequestConfig)
1786       */
1787      public SELF defaultRequestConfig(RequestConfig config) {
1788         httpClientBuilder().setDefaultRequestConfig(config);
1789         return self();
1790      }
1791
1792      /**
1793       * Assigns default {@link SocketConfig}.
1794       *
1795       * <h5 class='section'>Notes:</h5><ul>
1796       *    <li class='note'>It is applied to both pools of the connection manager the default {@link #createConnectionManager()}
1797       *       builds.  It has no effect on a connection manager supplied through
1798       *       {@link #connectionManager(HttpClientConnectionManager)} or an overridden {@link #createConnectionManager()}.
1799       * </ul>
1800       *
1801       * @param config New property value.
1802       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
1803       * @return This object.
1804       * @see HttpClientBuilder#setDefaultSocketConfig(SocketConfig)
1805       */
1806      public SELF defaultSocketConfig(SocketConfig config) {
1807         this.defaultSocketConfig = config;
1808         httpClientBuilder().setDefaultSocketConfig(config);
1809         return self();
1810      }
1811
1812      /**
1813       * <i><l>RestClient</l> configuration property:&emsp;</i>  Enable leak detection.
1814       *
1815       * <p>
1816       * Enable client and request/response leak detection.
1817       *
1818       * <p>
1819       * Causes messages to be logged to the console if clients or request/response objects are not properly closed
1820       * when the <c>finalize</c> methods are invoked.
1821       *
1822       * <p>
1823       * Automatically enabled with {@link org.apache.juneau.marshall.Context.Builder#debug() Context.Builder#debug()}.
1824       *
1825       * <h5 class='section'>Example:</h5>
1826       * <p class='bjava'>
1827       *    <jc>// Create a client that logs a message if </jc>
1828       *    RestClient <jv>client</jv> = RestClient
1829       *       .<jsm>create</jsm>()
1830       *       .detectLeaks()
1831       *       .logToConsole()  <jc>// Also log the error message to System.err</jc>
1832       *       .build();
1833       *
1834       *    <jv>client</jv>.closeQuietly();  <jc>// Customized HttpClient won't be closed.</jc>
1835       * </p>
1836       *
1837       * @return This object.
1838       */
1839      public SELF detectLeaks() {
1840         detectLeaks = true;
1841         return self();
1842      }
1843
1844      /**
1845       * Opts every {@code @Remote}/{@code @Url} call made through this client out of the default deny-private SSRF
1846       * guardrail (see {@code org.apache.juneau.http.remote.RemoteUrlPolicy}), for local-dev/intranet targets that
1847       * are intentionally private.
1848       *
1849       * <p>
1850       * The effective per-call value is the logical OR of this setting, the
1851       * {@code RestClient.allowPrivateUrls} system property, and the {@code @Remote}/{@code @RemoteOp}
1852       * {@code allowPrivateUrls} annotation attribute: any one of the three opting in is sufficient. The {@code http}/
1853       * {@code https} scheme requirement is unaffected.
1854       *
1855       * @param value {@code true} to allow private/loopback/link-local/metadata {@code @Remote} targets. Default {@code false}.
1856       * @return This object.
1857       */
1858      public SELF allowPrivateUrls(boolean value) {
1859         allowPrivateUrls = value;
1860         return self();
1861      }
1862
1863      /**
1864       * Allows this client's SSRF-guarded {@code @Remote}/{@code @Url} calls to reach hosts inside the given
1865       * special-purpose address ranges that the default policy denies (see {@code org.apache.juneau.http.remote.RemoteUrlPolicy}).
1866       *
1867       * <p>
1868       * Same narrow semantics and validation as the JVM-wide {@code RestClient.allowAddressRanges} system property: each
1869       * entry is a CIDR range or single address (parsed without DNS) that must lie inside {@code 192.0.0.0/24},
1870       * {@code 198.18.0.0/15}, {@code 224.0.0.0/4}, {@code 240.0.0.0/4} or {@code ff00::/8}.  It never re-opens
1871       * loopback, link-local/cloud-metadata, private, unspecified or any other deny.
1872       *
1873       * <p>
1874       * The effective allow-list is the union of this setting and the system property.  Repeated calls accumulate.
1875       * An invalid entry fails {@link #build()} with an {@link IllegalArgumentException}.
1876       *
1877       * @param value The CIDR ranges or addresses to allow.  Can be <jk>null</jk> or empty (no effect).
1878       * @return This object.
1879       */
1880      public SELF allowAddressRanges(String...value) {
1881         if (nn(value))
1882            Collections.addAll(allowedAddressRanges, value);
1883         return self();
1884      }
1885
1886      /**
1887       * <i><l>BeanTraverse</l> configuration property:&emsp;</i>  Automatically detect POJO recursions.
1888       *
1889       * <p>
1890       * When enabled, specifies that recursions should be checked for during traversal.
1891       *
1892       * <p>
1893       * Recursions can occur when traversing models that aren't true trees but rather contain loops.
1894       * <br>In general, unchecked recursions cause stack-overflow-errors.
1895       * <br>These show up as {@link MarshallingRecursionException MarshallingRecursionException} with the message <js>"Depth too deep.  Stack overflow occurred."</js>.
1896       *
1897       * <h5 class='section'>Notes:</h5><ul>
1898       *    <li class='note'>
1899       *       Checking for recursion can cause a small performance penalty.
1900       * </ul>
1901       *
1902       * <h5 class='section'>Example:</h5>
1903       * <p class='bjava'>
1904       *    <jc>// Create a JSON client that automatically checks for recursions.</jc>
1905       *    RestClient <jv>client</jv> = RestClient
1906       *       .<jsm>create</jsm>()
1907       *       .json()
1908       *       .detectRecursions()
1909       *       .build();
1910       *
1911       *    <jc>// Create a POJO model with a recursive loop.</jc>
1912       *    <jk>public class</jk> A {
1913       *       <jk>public</jk> Object <jf>f</jf>;
1914       *    }
1915       *    A <jv>a</jv> = <jk>new</jk> A();
1916       *    <jv>a</jv>.<jf>f</jf> = <jv>a</jv>;
1917       *
1918       * <jk>try</jk> {
1919       *       <jc>// Throws a RestCallException with an inner SerializeException and not a StackOverflowError</jc>
1920       *       <jv>client</jv>
1921       *          .post(<js>"http://localhost:10000/foo"</js>, <jv>a</jv>)
1922       *          .run();
1923       * } <jk>catch</jk> (RestCallException <jv>e</jv>} {
1924       *    <jc>// Handle exception.</jc>
1925       * }
1926       * </p>
1927       *
1928       * <h5 class='section'>See Also:</h5><ul>
1929       *    <li class='jm'>{@link org.apache.juneau.marshall.MarshallingTraverseContext.Builder#detectRecursions() MarshallingTraverseContext.Builder#detectRecursions()}
1930       * </ul>
1931       *
1932       * @return This object.
1933       */
1934      public SELF detectRecursions() {
1935         serializers().forEach(Serializer.Builder::detectRecursions);
1936         return self();
1937      }
1938
1939      /**
1940       * Disables authentication scheme caching.
1941       *
1942       * <h5 class='section'>Notes:</h5><ul>
1943       *    <li class='note'>This value can be overridden by the {@link #httpProcessor(HttpProcessor)} method.
1944       * </ul>
1945       *
1946       * @return This object.
1947       * @see HttpClientBuilder#disableAuthCaching()
1948       */
1949      public SELF disableAuthCaching() {
1950         httpClientBuilder().disableAuthCaching();
1951         return self();
1952      }
1953
1954      /**
1955       * Disables automatic request recovery and re-execution.
1956       *
1957       * @return This object.
1958       * @see HttpClientBuilder#disableAutomaticRetries()
1959       */
1960      public SELF disableAutomaticRetries() {
1961         httpClientBuilder().disableAutomaticRetries();
1962         return self();
1963      }
1964
1965      /**
1966       * Disables connection state tracking.
1967       *
1968       * @return This object.
1969       * @see HttpClientBuilder#disableConnectionState()
1970       */
1971      public SELF disableConnectionState() {
1972         httpClientBuilder().disableConnectionState();
1973         return self();
1974      }
1975
1976      /**
1977       * Disables automatic content decompression.
1978       *
1979       * <h5 class='section'>Notes:</h5><ul>
1980       *    <li class='note'>This value can be overridden by the {@link #httpProcessor(HttpProcessor)} method.
1981       * </ul>
1982       *
1983       * @return This object.
1984       * @see HttpClientBuilder#disableContentCompression()
1985       */
1986      public SELF disableContentCompression() {
1987         httpClientBuilder().disableContentCompression();
1988         return self();
1989      }
1990
1991      /**
1992       * Disables state (cookie) management.
1993       *
1994       * <h5 class='section'>Notes:</h5><ul>
1995       *    <li class='note'>This value can be overridden by the {@link #httpProcessor(HttpProcessor)} method.
1996       * </ul>
1997       *
1998       * @return This object.
1999       * @see HttpClientBuilder#disableCookieManagement()
2000       */
2001      public SELF disableCookieManagement() {
2002         httpClientBuilder().disableCookieManagement();
2003         return self();
2004      }
2005
2006      /**
2007       * Disables automatic redirect handling.
2008       *
2009       * @return This object.
2010       * @see HttpClientBuilder#disableRedirectHandling()
2011       */
2012      public SELF disableRedirectHandling() {
2013         httpClientBuilder().disableRedirectHandling();
2014         return self();
2015      }
2016
2017      /**
2018       * Errors codes predicate.
2019       *
2020       * <p>
2021       * Defines a predicate to test for error codes.
2022       *
2023       * <h5 class='section'>Example:</h5>
2024       * <p class='bjava'>
2025       *    <jc>// Create a client that considers any 300+ responses to be errors.</jc>
2026       *    RestClient <jv>client</jv> = RestClient
2027       *       .<jsm>create</jsm>()
2028       *       .errorCodes(<jv>x</jv> -&gt; <jv>x</jv>&gt;=300)
2029       *       .build();
2030       * </p>
2031       *
2032       * @param value
2033       *    The new value for this setting.
2034       *    <br>The default value is <code>x -&gt; x &gt;= 400</code>.
2035       *    <br>Cannot be <jk>null</jk>.
2036       * @return This object.
2037       */
2038      public SELF errorCodes(Predicate<Integer> value) {
2039         errorCodes = reqnn("value", value);
2040         return self();
2041      }
2042
2043      /**
2044       * Makes this instance of {@link HttpClient} proactively evict expired connections from the connection pool using a background thread.
2045       *
2046       * <h5 class='section'>Notes:</h5><ul>
2047       *    <li class='note'>One MUST explicitly close HttpClient with {@link CloseableHttpClient#close()} in order to stop and release the background thread.
2048       *    <li class='note'>This method has no effect if the instance of {@link HttpClient} is configured to use a shared connection manager.
2049       *    <li class='note'>This method may not be used when the instance of {@link HttpClient} is created inside an EJB container.
2050       * </ul>
2051       *
2052       * @return This object.
2053       * @see HttpClientBuilder#evictExpiredConnections()
2054       */
2055      public SELF evictExpiredConnections() {
2056         httpClientBuilder().evictExpiredConnections();
2057         return self();
2058      }
2059
2060      /**
2061       * Makes this instance of {@link HttpClient} proactively evict idle connections from the connection pool using a background thread.
2062       *
2063       * <h5 class='section'>Notes:</h5><ul>
2064       *    <li class='note'>One MUST explicitly close HttpClient with {@link CloseableHttpClient#close()} in order to stop and release the background thread.
2065       *    <li class='note'>This method has no effect if the instance of {@link HttpClient} is configured to use a shared connection manager.
2066       *    <li class='note'>This method may not be used when the instance of {@link HttpClient} is created inside an EJB container.
2067       * </ul>
2068       *
2069       * @param maxIdleTime New property value.
2070       * @param maxIdleTimeUnit New property value.
2071       *    <br>Cannot be <jk>null</jk>.
2072       * @return This object.
2073       * @see HttpClientBuilder#evictIdleConnections(long,TimeUnit)
2074       */
2075      public SELF evictIdleConnections(long maxIdleTime, TimeUnit maxIdleTimeUnit) {
2076         httpClientBuilder().evictIdleConnections(maxIdleTime, maxIdleTimeUnit);
2077         return self();
2078      }
2079
2080      /**
2081       * <i><l>RestClient</l> configuration property:&emsp;</i>  Executor service.
2082       *
2083       * <p>
2084       * Defines the executor service to use when calling future methods on the {@link RestRequest} class.
2085       *
2086       * <p>
2087       * This executor service is used to create {@link Future} objects on the following methods:
2088       * <ul>
2089       *    <li class='jm'>{@link RestRequest#runFuture()}
2090       *    <li class='jm'>{@link RestRequest#completeFuture()}
2091       *    <li class='jm'>{@link ResponseContent#asFuture(Class)} (and similar methods)
2092       * </ul>
2093       *
2094       * <p>
2095       * The default executor service is a single-threaded {@link ThreadPoolExecutor} with a 30 second timeout
2096       * and a queue size of 10.
2097       *
2098       * <h5 class='section'>Example:</h5>
2099       * <p class='bjava'>
2100       *    <jc>// Create a client with a customized executor service.</jc>
2101       *    RestClient <jv>client</jv> = RestClient
2102       *       .<jsm>create</jsm>()
2103       *       .executorService(<jk>new</jk> ThreadPoolExecutor(1, 1, 30, TimeUnit.<jsf>SECONDS</jsf>, <jk>new</jk> ArrayBlockingQueue&lt;Runnable&gt;(10)), <jk>true</jk>)
2104       *       .build();
2105       *
2106       *    <jc>// Use it to asynchronously run a request.</jc>
2107       *    Future&lt;RestResponse&gt; <jv>responseFuture</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).runFuture();
2108       *
2109       *    <jc>// Do some other stuff.</jc>
2110       *
2111       *    <jc>// Now read the response.</jc>
2112       *    String <jv>body</jv> = <jv>responseFuture</jv>.get().getContent().asString();
2113       *
2114       *    <jc>// Use it to asynchronously retrieve a response.</jc>
2115       *    Future&lt;MyBean&gt; <jv>myBeanFuture</jv> = <jv>client</jv>
2116       *       .get(<jsf>URI</jsf>)
2117       *       .run()
2118       *       .getContent().asFuture(MyBean.<jk>class</jk>);
2119       *
2120       *    <jc>// Do some other stuff.</jc>
2121       *
2122       *    <jc>// Now read the response.</jc>
2123       *    MyBean <jv>bean</jv> = <jv>myBeanFuture</jv>.get();
2124       * </p>
2125       *
2126       * @param executorService The executor service.
2127       *    <br>Can be <jk>null</jk> (a default executor service will be created if needed).
2128       * @param shutdownOnClose Call {@link ExecutorService#shutdown()} when {@link RestClient#close()} is called.
2129       * @return This object.
2130       */
2131      public SELF executorService(ExecutorService executorService, boolean shutdownOnClose) {
2132         this.executorService = executorService;
2133         this.executorServiceShutdownOnClose = shutdownOnClose;
2134         return self();
2135      }
2136
2137      /**
2138       * Returns the builder for the list of form data parameters that get applied to all requests created by this builder.
2139       *
2140       * <p>
2141       * This is the primary method for accessing the form data parameter list.
2142       * On first call, the builder is created via the method {@link #createFormData()}.
2143       *
2144       * <h5 class='section'>Example:</h5>
2145       * <p class='bjava'>
2146       *    <jc>// Create a client that adds a "foo=bar" form-data parameter on every request.</jc>
2147       *    RestClient.Builder&lt;?&gt; <jv>builder</jv> = RestClient.<jsm>create</jsm>();
2148       *    <jv>builder</jv>.formData().setDefault(<js>"foo"</js>, <js>"bar"</js>));
2149       *    RestClient <jv>client</jv> = <jv>builder</jv>.build();
2150       * </p>
2151       *
2152       * <p>
2153       * The following convenience methods are also provided for updating the parameters:
2154       * <ul>
2155       *    <li class='jm'>{@link #formData(NameValuePair...)}
2156       *    <li class='jm'>{@link #formDataDefault(NameValuePair...)}
2157       *    <li class='jm'>{@link #formData(String,String)}
2158       *    <li class='jm'>{@link #formData(String,Supplier)}
2159       * </ul>
2160       *
2161       * @return The form data list builder.
2162       */
2163      public final PartList formData() {
2164         if (formData == null)
2165            formData = createFormData();
2166         return formData;
2167      }
2168
2169      /**
2170       * Appends multiple form-data parameters to the request bodies of all URL-encoded form posts.
2171       *
2172       * <h5 class='section'>Example:</h5>
2173       * <p class='bjava'>
2174       *    <jk>import static</jk> org.apache.juneau.http.HttpParts.*;
2175       *
2176       *    RestClient <jv>client</jv> = RestClient
2177       *       .<jsm>create</jsm>()
2178       *       .formData(
2179       *          <jsm>stringPart</jsm>(<js>"foo"</js>, <js>"bar"</js>),
2180       *          <jsm>booleanPart</jsm>(<js>"baz"</js>, <jk>true</jk>)
2181       *       )
2182       *       .build();
2183       * </p>
2184       *
2185       * <p>
2186       * This is a shortcut for calling <c>formData().append(<jv>parts</jv>)</c>.
2187       *
2188       * @param parts
2189       *    The form-data parameters.
2190       *    <br>Can contain <jk>null</jk> values (ignored).
2191       * @return This object.
2192       * @see #formData()
2193       */
2194      public SELF formData(NameValuePair...parts) {
2195         formData().append(parts);
2196         return self();
2197      }
2198
2199      /**
2200       * Appends a form-data parameter to all request bodies.
2201       *
2202       * <h5 class='section'>Example:</h5>
2203       * <p class='bjava'>
2204       *    RestClient <jv>client</jv> = RestClient
2205       *       .<jsm>create</jsm>()
2206       *       .formData(<js>"foo"</js>, <js>"bar"</js>)
2207       *       .build();
2208       * </p>
2209       *
2210       * <p>
2211       * This is a shortcut for calling <c>formData().append(<jv>name</jv>,<jv>value</jv>)</c>.
2212       *
2213       * @param name The parameter name.
2214       *    <br>Cannot be <jk>null</jk>.
2215       * @param value The parameter value.
2216       *    <br>Can be <jk>null</jk> (null value will be serialized).
2217       * @return This object.
2218       * @see #formData()
2219       */
2220      public SELF formData(String name, String value) {
2221         formData().append(name, value);
2222         return self();
2223      }
2224
2225      /**
2226       * Appends a form-data parameter with a dynamic value to all request bodies.
2227       *
2228       * <h5 class='section'>Example:</h5>
2229       * <p class='bjava'>
2230       *    RestClient <jv>client</jv> = RestClient
2231       *       .<jsm>create</jsm>()
2232       *       .formData(<js>"foo"</js>, ()-&gt;<js>"bar"</js>)
2233       *       .build();
2234       * </p>
2235       *
2236       * <p>
2237       * This is a shortcut for calling <c>formData().append(<jv>name</jv>,<jv>value</jv>)</c>.
2238       *
2239       * @param name The parameter name.
2240       *    <br>Cannot be <jk>null</jk>.
2241       * @param value The parameter value supplier.
2242       *    <br>Can be <jk>null</jk> (null value will be serialized).
2243       * @return This object.
2244       * @see #formData()
2245       */
2246      public SELF formData(String name, Supplier<String> value) {
2247         formData().append(name, value);
2248         return self();
2249      }
2250
2251      /**
2252       * Sets default form-data parameter values.
2253       *
2254       * <p>
2255       * Uses default values for specified parameters if not otherwise specified on the outgoing requests.
2256       *
2257       * <h5 class='section'>Example:</h5>
2258       * <p class='bjava'>
2259       *    RestClient <jv>client</jv> = RestClient
2260       *       .<jsm>create</jsm>()
2261       *       .formDataDefault(<jsm>stringPart</jsm>(<js>"foo"</js>, ()-&gt;<js>"bar"</js>));
2262       *       .build();
2263       * </p>
2264       *
2265       * <p>
2266       * This is a shortcut for calling <c>formData().setDefault(<jv>parts</jv>)</c>.
2267       *
2268       * @param parts The parts.
2269       *    <br>Can contain <jk>null</jk> values (ignored).
2270       * @return This object.
2271       * @see #formData()
2272       */
2273      public SELF formDataDefault(NameValuePair...parts) {
2274         formData().setDefault(parts);
2275         return self();
2276      }
2277
2278      /**
2279       * Returns the root URI defined for this client.
2280       *
2281       * <p>
2282       * Returns <jk>null</jk> in lieu of an empty string.
2283       * Trailing slashes are trimmed.
2284       *
2285       * @return The root URI defined for this client.
2286       */
2287      public String getRootUri() { return rootUrl != null ? rootUrl.get() : null; }
2288
2289      /**
2290       * Returns the root URL supplier set on this builder.
2291       *
2292       * @return The root URL supplier, or <jk>null</jk> if not set.
2293       */
2294      public Supplier<String> getRootUrlSupplier() { return rootUrl; }
2295
2296      /**
2297       * Appends a header to all requests.
2298       *
2299       * <h5 class='section'>Example:</h5>
2300       * <p class='bjava'>
2301       *    RestClient <jv>client</jv> = RestClient
2302       *       .<jsm>create</jsm>()
2303       *       .header(<js>"Foo"</js>, <js>"bar"</js>);
2304       *       .build();
2305       * </p>
2306       *
2307       * <p>
2308       * This is a shortcut for calling <c>headerData().append(<jv>name</jv>,<jv>value</jv>)</c>.
2309       *
2310       * @param name The header name.
2311       *    <br>Cannot be <jk>null</jk>.
2312       * @param value The header value.
2313       *    <br>Can be <jk>null</jk> (null value will be serialized).
2314       * @return This object.
2315       * @see #headers()
2316       */
2317      public SELF header(String name, String value) {
2318         headers().append(name, value);
2319         return self();
2320      }
2321
2322      /**
2323       * Appends a header to all requests using a dynamic value.
2324       *
2325       * <h5 class='section'>Example:</h5>
2326       * <p class='bjava'>
2327       *    RestClient <jv>client</jv> = RestClient
2328       *       .<jsm>create</jsm>()
2329       *       .header(<js>"Foo"</js>, ()-&gt;<js>"bar"</js>);
2330       *       .build();
2331       * </p>
2332       *
2333       * <p>
2334       * This is a shortcut for calling <c>headerData().append(<jv>name</jv>,<jv>value</jv>)</c>.
2335       *
2336       * @param name The header name.
2337       *    <br>Cannot be <jk>null</jk>.
2338       * @param value The header value supplier.
2339       *    <br>Can be <jk>null</jk> (null value will be serialized).
2340       * @return This object.
2341       * @see #headers()
2342       */
2343      public SELF header(String name, Supplier<String> value) {
2344         headers().append(name, value);
2345         return self();
2346      }
2347
2348      /**
2349       * Returns the builder for the list of headers that get applied to all requests created by this builder.
2350       *
2351       * <p>
2352       * This is the primary method for accessing the request header list.
2353       * On first call, the builder is created via the method {@link #createHeaderData()}.
2354       *
2355       * <h5 class='section'>Example:</h5>
2356       * <p class='bjava'>
2357       *    <jc>// Create a client that adds a "Foo: bar" header on every request.</jc>
2358       *    RestClient.Builder&lt;?&gt; <jv>builder</jv> = RestClient.<jsm>create</jsm>();
2359       *    <jv>builder</jv>.headerData().setDefault(<js>"Foo"</js>, <js>"bar"</js>));
2360       *    RestClient <jv>client</jv> = <jv>builder</jv>.build();
2361       * </p>
2362       *
2363       * <p>
2364       * The following convenience methods are also provided for updating the headers:
2365       * <ul>
2366       *    <li class='jm'>{@link #headers(Header...)}
2367       *    <li class='jm'>{@link #headersDefault(Header...)}
2368       *    <li class='jm'>{@link #header(String,String)}
2369       *    <li class='jm'>{@link #header(String,Supplier)}
2370       *    <li class='jm'>{@link #mediaType(String)}
2371       *    <li class='jm'>{@link #mediaType(MediaType)}
2372       *    <li class='jm'>{@link #accept(String)}
2373       *    <li class='jm'>{@link #acceptCharset(String)}
2374       *    <li class='jm'>{@link #clientVersion(String)}
2375       *    <li class='jm'>{@link #contentType(String)}
2376       *    <li class='jm'>{@link #debug()}
2377       *    <li class='jm'>{@link #noTrace()}
2378       * </ul>
2379       *
2380       * @return The header list builder.
2381       */
2382      public final HeaderList headers() {
2383         if (headerData == null)
2384            headerData = createHeaderData();
2385         return headerData;
2386      }
2387
2388      /**
2389       * Appends multiple headers to all requests.
2390       *
2391       * <h5 class='section'>Example:</h5>
2392       * <p class='bjava'>
2393       *    <jk>import static</jk> org.apache.juneau.http.HttpHeaders.*;
2394       *
2395       *    RestClient <jv>client</jv> = RestClient
2396       *       .<jsm>create</jsm>()
2397       *       .headers(
2398       *          <jsf>ACCEPT_TEXT_XML</jsf>,
2399       *          <jsm>stringHeader</jsm>(<js>"Foo"</js>, <js>"bar"</js>)
2400       *       )
2401       *       .build();
2402       * </p>
2403       *
2404       * <p>
2405       * This is a shortcut for calling <c>headerData().append(<jv>parts</jv>)</c>.
2406       *
2407       * @param parts
2408       *    The header to set.
2409       *    <br>Can contain <jk>null</jk> values (ignored).
2410       * @return This object.
2411       * @see #headers()
2412       */
2413      public SELF headers(Header...parts) {
2414         headers().append(parts);
2415         return self();
2416      }
2417
2418      /**
2419       * Sets default header values.
2420       *
2421       * <p>
2422       * Uses default values for specified headers if not otherwise specified on the outgoing requests.
2423       *
2424       * <h5 class='section'>Example:</h5>
2425       * <p class='bjava'>
2426       *    RestClient <jv>client</jv> = RestClient
2427       *       .<jsm>create</jsm>()
2428       *       .headersDefault(<jsm>stringHeader</jsm>(<js>"Foo"</js>, ()-&gt;<js>"bar"</js>));
2429       *       .build();
2430       * </p>
2431       *
2432       * <p>
2433       * This is a shortcut for calling <c>headerData().setDefault(<jv>parts</jv>)</c>.
2434       *
2435       * @param parts The header values.
2436       *    <br>Can contain <jk>null</jk> values (ignored).
2437       * @return This object.
2438       * @see #headers()
2439       */
2440      public SELF headersDefault(Header...parts) {
2441         headers().setDefault(parts);
2442         return self();
2443      }
2444
2445      /**
2446       * Sets a default request header with serializer session options (JSON5 map) for all requests.
2447       *
2448       * <p>
2449       * This is a shortcut for <c>headersDefault(basicHeader({@link RestSharedConstants#HEADER_JuneauSerializerOptions}, <jv>json5</jv>))</c>.
2450       *
2451       * @param json5
2452       *    Serializer session options in JSON5 form.
2453       *    <br>Can be <jk>null</jk> (default is not set by this method).
2454       * @return This object.
2455       */
2456      public SELF serializerSessionOptionsHeader(String json5) {
2457         if (json5 != null)
2458            headersDefault(basicHeader(HEADER_JuneauSerializerOptions, json5));
2459         return self();
2460      }
2461
2462      /**
2463       * Sets a default request header with parser session options (JSON5 map) for all requests.
2464       *
2465       * <p>
2466       * This is a shortcut for <c>headersDefault(basicHeader({@link RestSharedConstants#HEADER_JuneauParserOptions}, <jv>json5</jv>))</c>.
2467       *
2468       * @param json5
2469       *    Parser session options in JSON5 form.
2470       *    <br>Can be <jk>null</jk> (default is not set by this method).
2471       * @return This object.
2472       */
2473      public SELF parserSessionOptionsHeader(String json5) {
2474         if (json5 != null)
2475            headersDefault(basicHeader(HEADER_JuneauParserOptions, json5));
2476         return self();
2477      }
2478
2479      /**
2480       * Convenience for {@link #serializerSessionOptionsHeader(String)} using a map serialized with JSON5.
2481       *
2482       * @param properties
2483       *    Property names and values for serializer session options.
2484       *    <br>Can be <jk>null</jk> (treated as an empty map).
2485       * @return This object.
2486       */
2487      public SELF serializerSessionOptionsHeader(Map<String,?> properties) {
2488         try {
2489            return serializerSessionOptionsHeader(isEmpty(properties) ? null : Json5.of(properties));
2490         } catch (SerializeException e) {
2491            throw rex(e, "Could not serialize serializer session options header");
2492         }
2493      }
2494
2495      /**
2496       * Convenience for {@link #parserSessionOptionsHeader(String)} using a map serialized with JSON5.
2497       *
2498       * @param properties
2499       *    Property names and values for parser session options.
2500       *    <br>Can be <jk>null</jk> (treated as an empty map).
2501       * @return This object.
2502       */
2503      public SELF parserSessionOptionsHeader(Map<String,?> properties) {
2504         try {
2505            return parserSessionOptionsHeader(isEmpty(properties) ? null : Json5.of(properties));
2506         } catch (SerializeException e) {
2507            throw rex(e, "Could not serialize parser session options header");
2508         }
2509      }
2510
2511      /**
2512       * Convenience method for specifying HTML as the marshalling transmission media type.
2513       *
2514       * <p>
2515       * POJOs are converted to HTML without any sort of doc wrappers.
2516       *
2517       * <p>
2518       *    {@link HtmlSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
2519       *    <ul>
2520       *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link #sortCollections()}) or
2521       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
2522       *    </ul>
2523       * <p>
2524       *    {@link HtmlParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
2525       *    <ul>
2526       *       <li>The parser can be configured using any of the parser property setters (e.g. {@link #ignoreUnknownBeanProperties()}) or
2527       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
2528       *    </ul>
2529       * <p>
2530       *    <c>Accept</c> request header will be set to <js>"text/html"</js> unless overridden
2531       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
2532       * <p>
2533       *    <c>Content-Type</c> request header will be set to <js>"text/html"</js> unless overridden
2534       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
2535       * <p>
2536       *    Can be combined with other marshaller setters such as {@link #json()} to provide support for multiple languages.
2537       *    <ul>
2538       *       <li>When multiple languages are supported, the <c>Accept</c> and <c>Content-Type</c> headers control which marshallers are used, or uses the
2539       *       last-enabled language if the headers are not set.
2540       *    </ul>
2541       * <p>
2542       *    Identical to calling <c>serializer(HtmlSerializer.<jk>class</jk>).parser(HtmlParser.<jk>class</jk>)</c>.
2543       *
2544       * <h5 class='section'>Example:</h5>
2545       * <p class='bjava'>
2546       *    <jc>// Construct a client that uses HTML marshalling.</jc>
2547       *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().html().build();
2548       * </p>
2549       *
2550       * @return This object.
2551       */
2552      public SELF html() {
2553         return serializer(HtmlSerializer.class).parser(HtmlParser.class);
2554      }
2555
2556      /**
2557       * Convenience method for specifying HTML DOC as the marshalling transmission media type.
2558       *
2559       * <p>
2560       * POJOs are converted to fully renderable HTML pages.
2561       *
2562       * <p>
2563       *    {@link HtmlDocSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
2564       *    <ul>
2565       *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link #sortCollections()} or
2566       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
2567       *    </ul>
2568       * <p>
2569       *    {@link HtmlParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
2570       *    <ul>
2571       *       <li>The parser can be configured using any of the parser property setters (e.g. {@link #ignoreUnknownBeanProperties()}) or
2572       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
2573       *    </ul>
2574       * <p>
2575       *    <c>Accept</c> request header will be set to <js>"text/html"</js> unless overridden
2576       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
2577       * <p>
2578       *    <c>Content-Type</c> request header will be set to <js>"text/html"</js> unless overridden
2579       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
2580       * <p>
2581       *    Can be combined with other marshaller setters such as {@link #json()} to provide support for multiple languages.
2582       *    <ul>
2583       *       <li>When multiple languages are supported, the <c>Accept</c> and <c>Content-Type</c> headers control which marshallers are used, or uses the
2584       *       last-enabled language if the headers are not set.
2585       *    </ul>
2586       * <p>
2587       *    Identical to calling <c>serializer(HtmlDocSerializer.<jk>class</jk>).parser(HtmlParser.<jk>class</jk>)</c>.
2588       *
2589       * <h5 class='section'>Example:</h5>
2590       * <p class='bjava'>
2591       *    <jc>// Construct a client that uses HTML Doc marshalling.</jc>
2592       *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().htmlDoc().build();
2593       * </p>
2594       *
2595       * @return This object.
2596       */
2597      public SELF htmlDoc() {
2598         return serializer(HtmlDocSerializer.class).parser(HtmlParser.class);
2599      }
2600
2601      /**
2602       * Convenience method for specifying Stripped HTML DOC as the marshalling transmission media type.
2603       *
2604       * <p>
2605       * Same as {@link #htmlDoc()} but without the header and body tags and page title and description.
2606       *
2607       * <p>
2608       *    {@link HtmlStrippedDocSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
2609       *    <ul>
2610       *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link #sortCollections()}) or
2611       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
2612       *    </ul>
2613       * <p>
2614       *    {@link HtmlParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
2615       *    <ul>
2616       *       <li>The parser can be configured using any of the parser property setters (e.g. {@link #ignoreUnknownBeanProperties()}) or
2617       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
2618       *    </ul>
2619       * <p>
2620       *    <c>Accept</c> request header will be set to <js>"text/html+stripped"</js> unless overridden
2621       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
2622       * <p>
2623       *    <c>Content-Type</c> request header will be set to <js>"text/html+stripped"</js> unless overridden
2624       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
2625       * <p>
2626       *    Can be combined with other marshaller setters such as {@link #json()} to provide support for multiple languages.
2627       *    <ul>
2628       *       <li>When multiple languages are supported, the <c>Accept</c> and <c>Content-Type</c> headers control which marshallers are used, or uses the
2629       *       last-enabled language if the headers are not set.
2630       *    </ul>
2631       * <p>
2632       *    Identical to calling <c>serializer(HtmlStrippedDocSerializer.<jk>class</jk>).parser(HtmlParser.<jk>class</jk>)</c>.
2633       *
2634       * <h5 class='section'>Example:</h5>
2635       * <p class='bjava'>
2636       *    <jc>// Construct a client that uses HTML Stripped Doc marshalling.</jc>
2637       *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().htmlStrippedDoc().build();
2638       * </p>
2639       *
2640       * @return This object.
2641       */
2642      public SELF htmlStrippedDoc() {
2643         return serializer(HtmlStrippedDocSerializer.class).parser(HtmlParser.class);
2644      }
2645
2646      /**
2647       * Sets the {@link HttpClient} to be used to handle all HTTP communications with the target server.
2648       *
2649       * <p>
2650       * This can be used to bypass the client created by {@link #createHttpClient()} method.
2651       *
2652       * <h5 class='section'>Example:</h5>
2653       * <p class='bjava'>
2654       *    <jc>// Construct a client that uses a customized HttpClient.</jc>
2655       *    RestClient <jv>client</jv> = RestClient
2656       *       .<jsm>create</jsm>()
2657       *       .httpClient(HttpClientBuilder.<jsm>create</jsm>().build())
2658       *       .build();
2659       * </p>
2660       *
2661       * @param value The {@link HttpClient} to be used to handle all HTTP communications with the target server.
2662       *    <br>Can be <jk>null</jk> (a default client will be created).
2663       * @return This object.
2664       */
2665      public SELF httpClient(CloseableHttpClient value) {
2666         httpClient = value;
2667         return self();
2668      }
2669
2670      /**
2671       * Returns the HTTP client builder.
2672       *
2673       * @return The HTTP client builder.
2674       */
2675      public final HttpClientBuilder httpClientBuilder() {
2676         if (httpClientBuilder == null)
2677            httpClientBuilder = createHttpClientBuilder();
2678         return httpClientBuilder;
2679      }
2680
2681      /**
2682       * Sets the {@link HttpClientBuilder} that will be used to create the {@link HttpClient} used by {@link RestClient}.
2683       *
2684       * <p>
2685       * This can be used to bypass the builder created by {@link #createHttpClientBuilder()} method.
2686       *
2687       * <h5 class='section'>Example:</h5>
2688       * <p class='bjava'>
2689       *    <jc>// Construct a client that uses a customized HttpClientBuilder.</jc>
2690       *    RestClient <jv>client</jv> = RestClient
2691       *       .<jsm>create</jsm>()
2692       *       .httpClientBuilder(HttpClientBuilder.<jsm>create</jsm>())
2693       *       .build();
2694       * </p>
2695       *
2696       * <h5 class='section'>Notes:</h5><ul>
2697       *    <li class='note'>The TLS and connection-pool settings Apache {@link HttpClientBuilder} applies only to a
2698       *       connection manager it builds itself
2699       *       ({@link HttpClientBuilder#setSSLContext(SSLContext) setSSLContext},
2700       *       {@link HttpClientBuilder#setSSLSocketFactory(LayeredConnectionSocketFactory) setSSLSocketFactory},
2701       *       {@link HttpClientBuilder#setSSLHostnameVerifier(HostnameVerifier) setSSLHostnameVerifier},
2702       *       {@link HttpClientBuilder#setPublicSuffixMatcher(PublicSuffixMatcher) setPublicSuffixMatcher},
2703       *       {@link HttpClientBuilder#setMaxConnTotal(int) setMaxConnTotal},
2704       *       {@link HttpClientBuilder#setMaxConnPerRoute(int) setMaxConnPerRoute},
2705       *       {@link HttpClientBuilder#setConnectionTimeToLive(long, TimeUnit) setConnectionTimeToLive},
2706       *       {@link HttpClientBuilder#setDefaultSocketConfig(SocketConfig) setDefaultSocketConfig},
2707       *       {@link HttpClientBuilder#setDefaultConnectionConfig(ConnectionConfig) setDefaultConnectionConfig},
2708       *       {@link HttpClientBuilder#setDnsResolver(DnsResolver) setDnsResolver} and
2709       *       {@link HttpClientBuilder#useSystemProperties() useSystemProperties}) are read from the given builder and
2710       *       applied to the connection manager the default {@link #createConnectionManager()} builds (see there).
2711       *    <li class='note'>These connection-manager settings, made through a method of this builder before this method is
2712       *       called, are applied too, and win over the same setting on the given builder:
2713       *       {@link #sslContext(SSLContext) sslContext},
2714       *       {@link #sslSocketFactory(LayeredConnectionSocketFactory) sslSocketFactory},
2715       *       {@link #sslHostnameVerifier(HostnameVerifier) sslHostnameVerifier},
2716       *       {@link #publicSuffixMatcher(PublicSuffixMatcher) publicSuffixMatcher} (for the default hostname verifier only:
2717       *       its use for cookies is lost with the replaced builder),
2718       *       {@link #maxConnTotal(int) maxConnTotal}, {@link #maxConnPerRoute(int) maxConnPerRoute}, {@link #pooled() pooled},
2719       *       {@link #connectionTimeToLive(long, TimeUnit) connectionTimeToLive},
2720       *       {@link #defaultSocketConfig(SocketConfig) defaultSocketConfig},
2721       *       {@link #defaultConnectionConfig(ConnectionConfig) defaultConnectionConfig} and the TLS and
2722       *       {@code http.maxConnections} system properties of {@link #useSystemProperties()}.  Every other setting made
2723       *       through this builder before this method is called (interceptors, proxy, the rest of
2724       *       {@code useSystemProperties()}, and so on) was made on the replaced builder and is lost.
2725       *    <li class='note'>For these connection-manager settings, a value set through a method of this builder always wins
2726       *       over the same setting on the {@code HttpClientBuilder}, whichever was set last: unlike Apache's own
2727       *       last-write-wins, a later {@code httpClientBuilder().setDefaultSocketConfig(...)} (and so on) does not
2728       *       override an earlier {@link #defaultSocketConfig(SocketConfig) defaultSocketConfig(...)}.
2729       *    <li class='note'>As in Apache {@code HttpClientBuilder}, an SSL socket factory wins over an SSL context wherever
2730       *       each was set: a {@link HttpClientBuilder#setSSLSocketFactory(LayeredConnectionSocketFactory) setSSLSocketFactory}
2731       *       on the given builder wins over an earlier {@link #sslContext(SSLContext) sslContext}.
2732       *    <li class='warn'>A socket factory set with {@code setSSLSocketFactory} on the given builder is used for
2733       *       SSRF-guard-active {@code @Remote} calls too, and must connect to exactly the address it is given (see
2734       *       {@link #sslSocketFactory(LayeredConnectionSocketFactory)}).
2735       *    <li class='warn'>A client built by an {@code HttpClientBuilder} subclass that overrides (or inherits an override
2736       *       of) {@code build()}, {@code createMainExec(...)}, {@code decorateMainExec(...)} or
2737       *       {@code decorateProtocolExec(...)} refuses every SSRF-guard-active {@code @Remote} call: the override may
2738       *       build the client around another connection manager or request executor.
2739       * </ul>
2740       *
2741       * @param value The {@link HttpClientBuilder} that will be used to create the {@link HttpClient} used by {@link RestClient}.
2742       *    <br>Can be <jk>null</jk> (a default builder will be created).
2743       * @return This object.
2744       */
2745      public SELF httpClientBuilder(HttpClientBuilder value) {
2746         httpClientBuilder = value;
2747         return self();
2748      }
2749
2750      /**
2751       * Assigns {@link HttpProcessor} instance.
2752       *
2753       * <h5 class='section'>Notes:</h5><ul>
2754       *    <li class='warn'>The processor replaces all of the client's request interceptors, among them the ones that
2755       *       enforce the SSRF guard and strip credentials on cross-origin redirects.  So a client with one refuses every
2756       *       SSRF-guard-active {@code @Remote} call (one without the {@link #allowPrivateUrls(boolean) allowPrivateUrls}
2757       *       opt-in).  Add interceptors with {@link HttpClientBuilder#addInterceptorLast(HttpRequestInterceptor)} on the
2758       *       {@link #httpClientBuilder() HttpClientBuilder} instead.
2759       * </ul>
2760       *
2761       * @param httpprocessor New property value.
2762       * @return This object.
2763       * @see HttpClientBuilder#setHttpProcessor(HttpProcessor)
2764       */
2765      public SELF httpProcessor(HttpProcessor httpprocessor) {
2766         httpClientBuilder().setHttpProcessor(httpprocessor);
2767         return self();
2768      }
2769
2770      /**
2771       * Ignore errors.
2772       *
2773       * <p>
2774       * When enabled, HTTP error response codes (e.g. <l>&gt;=400</l>) will not cause a {@link RestCallException} to
2775       * be thrown.
2776       * <p>
2777       * Note that this is equivalent to <c>builder.errorCodes(x -&gt; <jk>false</jk>);</c>
2778       *
2779       * <h5 class='section'>Example:</h5>
2780       * <p class='bjava'>
2781       *    <jc>// Create a client that doesn't throws a RestCallException when a 500 error occurs.</jc>
2782       *    RestClient
2783       *       .<jsm>create</jsm>()
2784       *       .ignoreErrors()
2785       *       .build()
2786       *       .get(<js>"/error"</js>)  <jc>// Throws a 500 error</jc>
2787       *       .run()
2788       *       .assertStatus().is(500);
2789       * </p>
2790       *
2791       * @return This object.
2792       */
2793      public SELF ignoreErrors() {
2794         ignoreErrors = true;
2795         return self();
2796      }
2797
2798      /**
2799       * <i><l>BeanTraverse</l> configuration property:&emsp;</i>  Ignore recursion errors.
2800       *
2801       * <p>
2802       * When enabled, when we encounter the same object when traversing a tree, we set the value to <jk>null</jk>.
2803       *
2804       * <p>
2805       * For example, if a model contains the links A-&gt;B-&gt;C-&gt;A, then the JSON generated will look like
2806       *    the following when <jsf>BEANTRAVERSE_ignoreRecursions</jsf> is <jk>true</jk>...
2807       *
2808       * <p class='bjson'>
2809       *    {A:{B:{C:<jk>null</jk>}}}
2810       * </p>
2811       *
2812       * <h5 class='section'>Notes:</h5><ul>
2813       *    <li class='note'>
2814       *       Checking for recursion can cause a small performance penalty.
2815       * </ul>
2816       *
2817       * <h5 class='section'>Example:</h5>
2818       * <p class='bjava'>
2819       *    <jc>// Create a JSON client that ignores recursions.</jc>
2820       *    RestClient <jv>client</jv> = RestClient
2821       *       .<jsm>create</jsm>()
2822       *       .json()
2823       *       .ignoreRecursions()
2824       *       .build();
2825       *
2826       *    <jc>// Create a POJO model with a recursive loop.</jc>
2827       *    <jk>public class</jk> A {
2828       *       <jk>public</jk> Object <jf>f</jf>;
2829       *    }
2830       *    A <jv>a</jv> = <jk>new</jk> A();
2831       *    <jv>a</jv>.<jf>f</jf> = <jv>a</jv>;
2832       *
2833       *    <jc>// Produces request body "{f:null}"</jc>
2834       *    <jv>client</jv>
2835       *       .post(<js>"http://localhost:10000/foo"</js>, <jv>a</jv>)
2836       *       .run();
2837       * </p>
2838       *
2839       * <h5 class='section'>See Also:</h5><ul>
2840       *    <li class='jm'>{@link org.apache.juneau.marshall.MarshallingTraverseContext.Builder#ignoreRecursions() MarshallingTraverseContext.Builder#ignoreRecursions()}
2841       * </ul>
2842       *
2843       * @return This object.
2844       */
2845      public SELF ignoreRecursions() {
2846         serializers().forEach(Serializer.Builder::ignoreRecursions);
2847         return self();
2848      }
2849
2850      /**
2851       * <i><l>BeanTraverse</l> configuration property:&emsp;</i>  Initial depth.
2852       *
2853       * <p>
2854       * The initial indentation level at the root.
2855       *
2856       * <p>
2857       * Useful when constructing document fragments that need to be indented at a certain level when whitespace is enabled.
2858       *
2859       * <h5 class='section'>Example:</h5>
2860       * <p class='bjava'>
2861       *    <jc>// Create a REST client with JSON serializer with whitespace enabled and an initial depth of 2.</jc>
2862       *    RestClient <jv>client</jv> = RestClient
2863       *       .<jsm>create</jsm>()
2864       *       .json()
2865       *       .ws()
2866       *       .initialDepth(2)
2867       *       .build();
2868       *
2869       *    <jc>// Our bean to serialize.</jc>
2870       *    <jk>public class</jk> MyBean {
2871       *       <jk>public</jk> String <jf>foo</jf> = <jk>null</jk>;
2872       *    }
2873       *
2874       *    <jc>// Produces request body "\t\t{\n\t\t\t'foo':'bar'\n\t\t}\n"</jc>
2875       *    <jv>client</jv>
2876       *       .post(<js>"http://localhost:10000/foo"</js>, <jk>new</jk> MyBean())
2877       *       .run();
2878       * </p>
2879       *
2880       * <h5 class='section'>See Also:</h5><ul>
2881       *    <li class='jm'>{@link org.apache.juneau.marshall.MarshallingTraverseContext.Builder#initialDepth(int) MarshallingTraverseContext.Builder#initialDepth(int)}
2882       * </ul>
2883       *
2884       * @param value
2885       *    The new value for this property.
2886       *    <br>The default is <c>0</c>.
2887       * @return This object.
2888       */
2889      public SELF initialDepth(int value) {
2890         serializers().forEach(x -> x.initialDepth(value));
2891         return self();
2892      }
2893
2894      /**
2895       * <i><l>RestClient</l> configuration property:&emsp;</i>  Call interceptors.
2896       *
2897       * <p>
2898       * Adds an interceptor that can be called to hook into specified events in the lifecycle of a single request.
2899       *
2900       * <h5 class='section'>Example:</h5>
2901       * <p class='bjava'>
2902       *   <jc>// Customized interceptor (note you can also extend from BasicRestCallInterceptor as well.</jc>
2903       *    <jk>public class</jk> MyRestCallInterceptor <jk>implements</jk> RestCallInterceptor {
2904       *
2905       *       <ja>@Override</ja>
2906       *       <jk>public void</jk> onInit(RestRequest <jv>req</jv>) <jk>throws</jk> Exception {
2907       *       <jc>// Intercept immediately after RestRequest object is created and all headers/query/form-data has been
2908       *       // set on the request from the client.</jc>
2909       *    }
2910       *
2911       *    <ja>@Override</ja>
2912       *    <jk>public void</jk> onConnect(RestRequest <jv>req</jv>, RestResponse <jv>res</jv>) <jk>throws</jk> Exception {
2913       *       <jc>// Intercept immediately after an HTTP response has been received.</jc>
2914       *    }
2915       *
2916       *    <ja>@Override</ja>
2917       *    <jk>public void</jk> onClose(RestRequest <jv>req</jv>, RestResponse <jv>res</jv>) <jk>throws</jk> Exception {
2918       *          <jc>// Intercept when the response body is consumed.</jc>
2919       *       }
2920       *    }
2921       *
2922       *    <jc>// Create a client with a customized interceptor.</jc>
2923       *    RestClient <jv>client</jv> = RestClient
2924       *       .<jsm>create</jsm>()
2925       *       .interceptors(MyRestCallInterceptor.<jk>class</jk>)
2926       *       .build();
2927       * </p>
2928       *
2929       * <h5 class='section'>Notes:</h5><ul>
2930       *    <li class='note'>The {@link RestClient#onCallInit(RestRequest)}, {@link RestClient#onCallConnect(RestRequest,RestResponse)}, and
2931       * {@link RestClient#onCallClose(RestRequest,RestResponse)} methods can also be overridden to produce the same results.
2932       * </ul>
2933       *
2934       * @param values
2935       *    The values to add to this setting.
2936       *    <br>Can be implementations of any of the following:
2937       *    <ul>
2938       *       <li class='jic'>{@link RestCallInterceptor}
2939       *       <li class='jic'>{@link HttpRequestInterceptor}
2940       *       <li class='jic'>{@link HttpResponseInterceptor}
2941       *    </ul>
2942       *    <br>Can contain <jk>null</jk> values (ignored).
2943       * @return This object.
2944       * @throws Exception If one or more interceptors could not be created.
2945       */
2946      public SELF interceptors(Class<?>...values) throws Exception {
2947         for (var c : values) {
2948            if (c == null)
2949               continue;
2950            var ci = ClassInfo.of(c);
2951            if (nn(ci)) {
2952               if (ci.isAssignableToAny(RestCallInterceptor.class, HttpRequestInterceptor.class, HttpResponseInterceptor.class))
2953                  interceptors(ci.newInstance());
2954               else
2955                  throw new ConfigException("Invalid class of type '%s' passed to interceptors().", ci.getName());
2956            }
2957         }
2958         return self();
2959      }
2960
2961      /**
2962       * Call interceptors.
2963       *
2964       * <p>
2965       * Adds an interceptor that gets called immediately after a connection is made.
2966       *
2967       * <h5 class='section'>Example:</h5>
2968       * <p class='bjava'>
2969       *    <jc>// Create a client with a customized interceptor.</jc>
2970       *    RestClient <jv>client</jv> = RestClient
2971       *       .<jsm>create</jsm>()
2972       *       .interceptors(
2973       *          <jk>new</jk> RestCallInterceptor() {
2974       *
2975       *             <ja>@Override</ja>
2976       *             <jk>public void</jk> onInit(RestRequest <jv>req</jv>) <jk>throws</jk> Exception {
2977       *             <jc>// Intercept immediately after RestRequest object is created and all headers/query/form-data has been
2978       *             // set on the request from the client.</jc>
2979       *          }
2980       *
2981       *          <ja>@Override</ja>
2982       *          <jk>public void</jk> onConnect(RestRequest <jv>req</jv>, RestResponse <jv>res</jv>) <jk>throws</jk> Exception {
2983       *             <jc>// Intercept immediately after an HTTP response has been received.</jc>
2984       *          }
2985       *
2986       *          <ja>@Override</ja>
2987       *          <jk>public void</jk> onClose(RestRequest <jv>req</jv>, RestResponse <jv>res</jv>) <jk>throws</jk> Exception {
2988       *                <jc>// Intercept when the response body is consumed.</jc>
2989       *             }
2990       *          }
2991       *       )
2992       *       .build();
2993       * </p>
2994       *
2995       * <h5 class='section'>Notes:</h5><ul>
2996       *    <li class='note'>The {@link RestClient#onCallInit(RestRequest)}, {@link RestClient#onCallConnect(RestRequest,RestResponse)}, and
2997       * {@link RestClient#onCallClose(RestRequest,RestResponse)} methods can also be overridden to produce the same results.
2998       * </ul>
2999       *
3000       * @param value
3001       *    The values to add to this setting.
3002       *    <br>Can be implementations of any of the following:
3003       *    <ul>
3004       *       <li class='jic'>{@link RestCallInterceptor}
3005       *       <li class='jic'>{@link HttpRequestInterceptor}
3006       *       <li class='jic'>{@link HttpResponseInterceptor}
3007       *    </ul>
3008       *    <br>Can contain <jk>null</jk> values (ignored).
3009       * @return This object.
3010       */
3011      public SELF interceptors(Object...value) {
3012         List<RestCallInterceptor> l = list();
3013         for (var o : value) {
3014            if (o == null)
3015               continue;
3016            ClassInfo ci = ClassInfo.of(o);
3017            if (nn(ci)) {
3018               if (! ci.isAssignableToAny(HttpRequestInterceptor.class, HttpResponseInterceptor.class, RestCallInterceptor.class))
3019                  throw new ConfigException("Invalid object of type '%s' passed to interceptors().", ci.getName());
3020               if (o instanceof HttpRequestInterceptor o2)
3021                  addInterceptorLast(o2);
3022               if (o instanceof HttpResponseInterceptor o2)
3023                  addInterceptorLast(o2);
3024               if (o instanceof RestCallInterceptor o2)
3025                  l.add(o2);
3026            }
3027         }
3028         if (interceptors == null)
3029            interceptors = l;
3030         else
3031            interceptors.addAll(0, l);
3032         return self();
3033      }
3034
3035      /**
3036       * Convenience method for specifying JSON as the marshalling transmission media type.
3037       *
3038       * <p>
3039       * {@link JsonSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
3040       *    <ul>
3041       *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link #sortCollections()}) or
3042       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
3043       *    </ul>
3044       * <p>
3045       *    {@link JsonParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
3046       *    <ul>
3047       *       <li>The parser can be configured using any of the parser property setters (e.g. {@link #ignoreUnknownBeanProperties()}) or
3048       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
3049       *    </ul>
3050       * <p>
3051       *    <c>Accept</c> request header will be set to <js>"application/json"</js> unless overridden
3052       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}}.
3053       * <p>
3054       *    <c>Content-Type</c> request header will be set to <js>"application/json"</js> unless overridden
3055       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
3056       * <p>
3057       *    Can be combined with other marshaller setters such as {@link #xml()} to provide support for multiple languages.
3058       *    <ul>
3059       *       <li>When multiple languages are supported, the <c>Accept</c> and <c>Content-Type</c> headers control which marshallers are used, or uses the
3060       *       last-enabled language if the headers are not set.
3061       *    </ul>
3062       * <p>
3063       *    Identical to calling <c>serializer(JsonSerializer.<jk>class</jk>).parser(JsonParser.<jk>class</jk>)</c>.
3064       *
3065       * <h5 class='section'>Example:</h5>
3066       * <p class='bjava'>
3067       *    <jc>// Construct a client that uses JSON marshalling.</jc>
3068       *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().json().build();
3069       * </p>
3070       *
3071       * @return This object.
3072       */
3073      public SELF json() {
3074         return serializer(JsonSerializer.class).parser(JsonParser.class);
3075      }
3076
3077      /**
3078       * Convenience method for specifying Simplified JSON as the marshalling transmission media type.
3079       *
3080       * <p>
3081       * Simplified JSON is typically useful for automated tests because you can do simple string comparison of results
3082       * without having to escape lots of quotes.
3083       *
3084       * <p>
3085       *    {@link Json5Serializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
3086       *    <ul>
3087       *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link #sortCollections()}) or
3088       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
3089       *    </ul>
3090       * <p>
3091       *    {@link Json5Parser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
3092       *    <ul>
3093       *       <li>The parser can be configured using any of the parser property setters (e.g. {@link #ignoreUnknownBeanProperties()}) or
3094       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
3095       *    </ul>
3096       * <p>
3097       *    <c>Accept</c> request header will be set to <js>"application/json5"</js> unless overridden
3098       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
3099       * <p>
3100       *    <c>Content-Type</c> request header will be set to <js>"application/json5"</js> unless overridden
3101       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
3102       * <p>
3103       *    A server that only handles JSON may reply <c>406 Not Acceptable</c> or <c>415 Unsupported Media Type</c> to these
3104       *    JSON5 media types.
3105       * <p>
3106       *    Can be combined with other marshaller setters such as {@link #xml()} to provide support for multiple languages.
3107       *    <ul>
3108       *       <li>When multiple languages are supported, the <c>Accept</c> and <c>Content-Type</c> headers control which marshallers are used, or uses the
3109       *       last-enabled language if the headers are not set.
3110       *    </ul>
3111       * <p>
3112       *    Identical to calling <c>serializer(Json5Serializer.<jk>class</jk>).parser(Json5Parser.<jk>class</jk>)</c>.
3113       *
3114       * <h5 class='section'>Example:</h5>
3115       * <p class='bjava'>
3116       *    <jc>// Construct a client that uses Simplified JSON marshalling.</jc>
3117       *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().json5().build();
3118       * </p>
3119       *
3120       * @return This object.
3121       */
3122      public SELF json5() {
3123         return serializer(Json5Serializer.class).parser(Json5Parser.class);
3124      }
3125
3126      /**
3127       * Convenience method for specifying JCS (JSON Canonicalization Scheme, RFC 8785) as the marshalling transmission media type.
3128       *
3129       * <p>
3130       *    {@link JcsSerializer} will be used to serialize POJOs to request bodies.
3131       *    {@link JsonParser} will be used to parse POJOs from response bodies (JCS output is valid JSON).
3132       * <p>
3133       *    <c>Accept</c> and <c>Content-Type</c> will be set to <js>"application/jcs+json"</js>.
3134       * <p>
3135       *    Identical to calling <c>serializer(JcsSerializer.<jk>class</jk>).parser(JsonParser.<jk>class</jk>)</c>.
3136       *
3137       * @return This object.
3138       */
3139      public SELF jcs() {
3140         return serializer(JcsSerializer.class).parser(JsonParser.class);
3141      }
3142
3143      /**
3144       * Assigns {@link ConnectionKeepAliveStrategy} instance.
3145       *
3146       * @param keepAliveStrategy New property value.
3147       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
3148       * @return This object.
3149       * @see HttpClientBuilder#setKeepAliveStrategy(ConnectionKeepAliveStrategy)
3150       */
3151      public SELF keepAliveStrategy(ConnectionKeepAliveStrategy keepAliveStrategy) {
3152         httpClientBuilder().setKeepAliveStrategy(keepAliveStrategy);
3153         return self();
3154      }
3155
3156      /**
3157       * <i><l>RestClient</l> configuration property:&emsp;</i>  Keep HttpClient open.
3158       *
3159       * <p>
3160       * Don't close this client when the {@link RestClient#close()} method is called.
3161       *
3162       * <h5 class='section'>Example:</h5>
3163       * <p class='bjava'>
3164       *    <jc>// Create a client with a customized client and don't close the client  service.</jc>
3165       *    RestClient <jv>client</jv> = RestClient
3166       *       .<jsm>create</jsm>()
3167       *       .httpClient(<jv>myHttpClient</jv>)
3168       *       .keepHttpClientOpen()
3169       *       .build();
3170       *
3171       *    <jv>client</jv>.closeQuietly();  <jc>// Customized HttpClient won't be closed.</jc>
3172       * </p>
3173       *
3174       * <h5 class='section'>Notes:</h5><ul>
3175       *    <li class='note'>When combined with {@link #connectionManagerShared(boolean) connectionManagerShared(true)}, the
3176       *       client's internal pool for SSRF-guard-active {@code @Remote} calls (see {@link #createConnectionManager()}) and
3177       *       the connection manager the default {@code createConnectionManager()} built are not shut down either, and
3178       *       nothing else shuts them down; their connections stay open until they are closed as idle or the JVM exits.
3179       * </ul>
3180       *
3181       * @return This object.
3182       */
3183      public SELF keepHttpClientOpen() {
3184         keepHttpClientOpen = true;
3185         return self();
3186      }
3187
3188      /**
3189       * <i><l>Serializer</l> configuration property:&emsp;</i>  Don't trim null bean property values.
3190       *
3191       * <p>
3192       * When enabled, null bean values will be serialized to the output.
3193       *
3194       * <h5 class='section'>Notes:</h5><ul>
3195       *    <li class='note'>Not enabling this setting will cause <c>Map</c>s with <jk>null</jk> values to be lost during parsing.
3196       * </ul>
3197       *
3198       * <h5 class='section'>Example:</h5>
3199       * <p class='bjava'>
3200       *    <jc>// Create a REST client with JSON serializer that serializes null properties.</jc>
3201       *    RestClient <jv>client</jv> = RestClient
3202       *       .<jsm>create</jsm>()
3203       *       .json()
3204       *       .keepNullProperties()
3205       *       .build();
3206       *
3207       *    <jc>// Our bean to serialize.</jc>
3208       *    <jk>public class</jk> MyBean {
3209       *       <jk>public</jk> String <jf>foo</jf> = <jk>null</jk>;
3210       *    }
3211       *
3212       *    <jc>// Request body will contain:  {foo:null}</jc>
3213       *    <jv>client</jv>
3214       *       .post(<js>"http://localhost:10000/foo"</js>, <jk>new</jk> MyBean())
3215       *       .run();
3216       * </p>
3217       *
3218       * <h5 class='section'>See Also:</h5><ul>
3219       *    <li class='jm'>{@link org.apache.juneau.marshall.serializer.Serializer.Builder#keepNullProperties() Serializer.Builder#keepNullProperties()}
3220       * </ul>
3221       *
3222       * @return This object.
3223       */
3224      public SELF keepNullProperties() {
3225         serializers().forEach(Serializer.Builder::keepNullProperties);
3226         return self();
3227      }
3228
3229      /**
3230       * Logger.
3231       *
3232       * <p>
3233       * Specifies the logger to use for logging.
3234       *
3235       * <p>
3236       * If not specified, uses the following logger:
3237       * <p class='bjava'>
3238       *    Logger.<jsm>getLogger</jsm>(RestClient.<jk>class</jk>.getName());
3239       * </p>
3240       *
3241       * <h5 class='section'>Example:</h5>
3242       * <p class='bjava'>
3243       *    <jc>// Construct a client that logs messages to a special logger.</jc>
3244       *    RestClient <jv>client</jv> = RestClient
3245       *       .<jsm>create</jsm>()
3246       *       .logger(Logger.<jsm>getLogger</jsm>(<js>"MyLogger"</js>))  <jc>// Log to MyLogger logger.</jc>
3247       *       .logToConsole()  <jc>// Also log to console.</jc>
3248       *       .logRequests(<jsf>FULL</jsf>, <jsf>WARNING</jsf>)  <jc>// Log requests with full detail at WARNING level.</jc>
3249       *       .build();
3250       * </p>
3251       *
3252       * @param value The logger to use for logging.
3253       *    <br>Can be <jk>null</jk> (defaults to <c>Logger.getLogger(RestClient.class.getName())</c>).
3254       * @return This object.
3255       */
3256      public SELF logger(Logger value) {
3257         logger = value;
3258         return self();
3259      }
3260
3261      /**
3262       * Log requests.
3263       *
3264       * <p>
3265       * Causes requests/responses to be logged at the specified log level at the end of the request.
3266       *
3267       * <p>
3268       * <jsf>SIMPLE</jsf> detail produces a log message like the following:
3269       * <p class='bconsole'>
3270       *    POST http://localhost:10000/testUrl, HTTP/1.1 200 OK
3271       * </p>
3272       *
3273       * <p>
3274       * <jsf>FULL</jsf> detail produces a log message like the following:
3275       * <p class='bconsole'>
3276       *    === HTTP Call (outgoing) =======================================================
3277       *    === REQUEST ===
3278       *    POST http://localhost:10000/testUrl
3279       *    ---request headers---
3280       *       Debug: true
3281       *       No-Trace: true
3282       *       Accept: application/json
3283       *    ---request entity---
3284       *       Content-Type: application/json
3285       *    ---request content---
3286       *    {"foo":"bar","baz":123}
3287       *    === RESPONSE ===
3288       *    HTTP/1.1 200 OK
3289       *    ---response headers---
3290       *       Content-Type: application/json;charset=utf-8
3291       *       Content-Length: 21
3292       *       Server: Jetty(8.1.0.v20120127)
3293       *    ---response content---
3294       *    {"message":"OK then"}
3295       *    === END ========================================================================
3296       * </p>
3297       *
3298       * <p>
3299       * By default, the message is logged to the default logger.  It can be logged to a different logger via the
3300       * {@link #logger(Logger)} method or logged to the console using the
3301       * {@link #logToConsole()} method.
3302       *
3303       * @param detail The detail level of logging.
3304       * @param level The log level.
3305       * @param test A predicate to use per-request to see if the request should be logged.  If <jk>null</jk>, always logs.
3306       * @return This object.
3307       */
3308      public SELF logRequests(DetailLevel detail, Level level, BiPredicate<RestRequest,RestResponse> test) {
3309         logRequests = detail;
3310         logRequestsLevel = level;
3311         logRequestsPredicate = test;
3312         return self();
3313      }
3314
3315      /**
3316       * Log to console.
3317       *
3318       * <p>
3319       * Specifies to log messages to the console.
3320       *
3321       * <h5 class='section'>Example:</h5>
3322       * <p class='bjava'>
3323       *    <jc>// Construct a client that logs messages to a special logger.</jc>
3324       *    RestClient <jv>client</jv> = RestClient
3325       *       .<jsm>create</jsm>()
3326       *       .logToConsole()
3327       *       .logRequests(<jsf>FULL</jsf>, <jsf>INFO</jsf>)  <jc>// Level is ignored when logging to console.</jc>
3328       *       .build();
3329       * </p>
3330       *
3331       * @return This object.
3332       */
3333      public SELF logToConsole() {
3334         logToConsole = true;
3335         return self();
3336      }
3337
3338      /**
3339       * <i><l>RestClient</l> configuration property:&emsp;</i>  Marshaller
3340       *
3341       * <p>
3342       * Shortcut for specifying the serializers and parsers
3343       * using the serializer and parser defined in a marshaller.
3344       *
3345       * <h5 class='section'>Notes:</h5><ul>
3346       *    <li class='note'>When using this method that takes in a pre-instantiated serializers and parsers, the serializer property setters (e.g. {@link #sortCollections()}),
3347       *    parser property setters (e.g. {@link #ignoreUnknownBeanProperties()}), or bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class have no effect.
3348       * </ul>
3349       *
3350       * <h5 class='section'>Example:</h5>
3351       * <p class='bjava'>
3352       *    <jc>// Create a client that uses Simplified-JSON transport using an existing marshaller.</jc>
3353       *    RestClient <jv>client</jv> = RestClient
3354       *       .<jsm>create</jsm>()
3355       *       .marshaller(Json5.<jsf>DEFAULT_READABLE</jsf>)
3356       *       .build();
3357       * </p>
3358       *
3359       * @param value The values to add to this setting.
3360       *    <br>Can be <jk>null</jk> (value will not be set, existing serializers and parsers will be kept).
3361       * @return This object.
3362       */
3363      public SELF marshaller(Marshaller value) {
3364         if (nn(value))
3365            serializer(value.getSerializer()).parser(value.getParser());
3366         return self();
3367      }
3368
3369      /**
3370       * <i><l>RestClient</l> configuration property:&emsp;</i>  Marshalls
3371       *
3372       * <p>
3373       * Shortcut for specifying the serializers and parsers
3374       * using the serializer and parser defined in a marshaller.
3375       *
3376       * <h5 class='section'>Notes:</h5><ul>
3377       *    <li class='note'>When using this method that takes in a pre-instantiated serializers and parsers, the serializer property setters (e.g. {@link #sortCollections()}),
3378       *    parser property setters (e.g. {@link #ignoreUnknownBeanProperties()}), or bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class have no effect.
3379       * </ul>
3380       *
3381       * <h5 class='section'>Example:</h5>
3382       * <p class='bjava'>
3383       *    <jc>// Create a client that uses JSON and XML transport using existing marshalls.</jc>
3384       *    RestClient <jv>client</jv> = RestClient
3385       *       .<jsm>create</jsm>()
3386       *       .marshaller(Json.<jsf>DEFAULT_READABLE</jsf>, Xml.<jsf>DEFAULT_READABLE</jsf>)
3387       *       .build();
3388       * </p>
3389       *
3390       * @param value The values to add to this setting.
3391       *    <br>Can contain <jk>null</jk> values (ignored).
3392       * @return This object.
3393       */
3394      public SELF marshallers(Marshaller...value) {
3395         for (var m : value)
3396            if (nn(m))
3397               serializer(m.getSerializer()).parser(m.getParser());
3398         return self();
3399      }
3400
3401      /**
3402       * Assigns maximum connection per route value.
3403       *
3404       * <h5 class='section'>Notes:</h5><ul>
3405       *    <li class='note'>A positive value is applied to the connection manager the default
3406       *       {@link #createConnectionManager()} builds, which is then always a {@link PoolingHttpClientConnectionManager}
3407       *       (as if {@link #pooled()} had been called), and to its internal pool for SSRF-guard-active {@code @Remote} calls.
3408       *    <li class='note'>It has no effect on a connection manager supplied through
3409       *       {@link #connectionManager(HttpClientConnectionManager)} or an overridden {@link #createConnectionManager()}.
3410       * </ul>
3411       *
3412       * @param maxConnPerRoute New property value.
3413       * @return This object.
3414       * @see HttpClientBuilder#setMaxConnPerRoute(int)
3415       */
3416      public SELF maxConnPerRoute(int maxConnPerRoute) {
3417         this.maxConnPerRoute = maxConnPerRoute;
3418         httpClientBuilder().setMaxConnPerRoute(maxConnPerRoute);
3419         return self();
3420      }
3421
3422      /**
3423       * Assigns maximum total connection value.
3424       *
3425       * <h5 class='section'>Notes:</h5><ul>
3426       *    <li class='note'>A positive value is applied to the connection manager the default
3427       *       {@link #createConnectionManager()} builds, which is then always a {@link PoolingHttpClientConnectionManager}
3428       *       (as if {@link #pooled()} had been called), and to its internal pool for SSRF-guard-active {@code @Remote} calls.
3429       *       Each pool applies the limit on its own (see {@link #createConnectionManager()}).
3430       *    <li class='note'>It has no effect on a connection manager supplied through
3431       *       {@link #connectionManager(HttpClientConnectionManager)} or an overridden {@link #createConnectionManager()}.
3432       * </ul>
3433       *
3434       * @param maxConnTotal New property value.
3435       * @return This object.
3436       * @see HttpClientBuilder#setMaxConnTotal(int)
3437       */
3438      public SELF maxConnTotal(int maxConnTotal) {
3439         this.maxConnTotal = maxConnTotal;
3440         httpClientBuilder().setMaxConnTotal(maxConnTotal);
3441         return self();
3442      }
3443
3444      /**
3445       * <i><l>BeanTraverse</l> configuration property:&emsp;</i>  Max serialization depth.
3446       *
3447       * <p>
3448       * When enabled, abort traversal if specified depth is reached in the POJO tree.
3449       *
3450       * <p>
3451       * If this depth is exceeded, an exception is thrown.
3452       *
3453       * <p>
3454       * This prevents stack overflows from occurring when trying to traverse models with recursive references.
3455       *
3456       * <h5 class='section'>Example:</h5>
3457       * <p class='bjava'>
3458       *    <jc>// Create a REST client with JSON serializer that throws an exception if the depth reaches greater than 20.</jc>
3459       *    RestClient <jv>client</jv> = RestClient
3460       *       .<jsm>create</jsm>()
3461       *       .json()
3462       *       .maxDepth(20)
3463       *       .build();
3464       * </p>
3465       *
3466       * <h5 class='section'>See Also:</h5><ul>
3467       *    <li class='jm'>{@link org.apache.juneau.marshall.MarshallingTraverseContext.Builder#maxDepth(int) MarshallingTraverseContext.Builder#maxDepth(int)}
3468       * </ul>
3469       *
3470       * @param value
3471       *    The new value for this property.
3472       *    <br>The default is <c>100</c>.
3473       * @return This object.
3474       */
3475      public SELF maxDepth(int value) {
3476         serializers().forEach(x -> x.maxDepth(value));
3477         return self();
3478      }
3479
3480      /**
3481       * <i><l>WriterSerializer</l> configuration property:&emsp;</i>  Maximum indentation.
3482       *
3483       * <p>
3484       * Specifies the maximum indentation level in the serialized document.
3485       *
3486       * <h5 class='section'>Notes:</h5><ul>
3487       *    <li class='note'>This setting does not apply to the RDF serializers.
3488       * </ul>
3489       *
3490       * <h5 class='section'>Example:</h5>
3491       * <p class='bjava'>
3492       *    <jc>// Create a REST client with JSON serializer that indents a maximum of 20 tabs.</jc>
3493       *    RestClient <jv>client</jv> = RestClient
3494       *       .<jsm>create</jsm>()
3495       *       .json()
3496       *       .ws()  <jc>// Enable whitespace</jc>
3497       *       .maxIndent(20)
3498       *       .build();
3499       * </p>
3500       *
3501       * <h5 class='section'>See Also:</h5><ul>
3502       *    <li class='jm'>{@link org.apache.juneau.marshall.serializer.WriterSerializer.Builder#maxIndent(int) WriterSerializer.Builder#maxIndent(int)}
3503       * </ul>
3504       *
3505       * @param value
3506       *    The new value for this property.
3507       *    <br>The default is <c>100</c>.
3508       * @return This object.
3509       */
3510      public SELF maxIndent(int value) {
3511         serializers().forEachWS(x -> x.maxIndent(value));
3512         return self();
3513      }
3514
3515      /**
3516       * Appends the <c>Accept</c> and <c>Content-Type</c> headers on all requests made by this client.
3517       *
3518       * <p>
3519       * Headers are appended to the end of the current header list.
3520       *
3521       * <p>
3522       * This is a shortcut for calling <c>headerData().append(Accept.<jsm>of</jsm>(<jv>value</jv>), ContentType.<jsm>of</jsm>(<jv>value</jv>))</c>.
3523       *
3524       * @param value The new header values.
3525       *    <br>Can be <jk>null</jk> (no Accept or Content-Type headers will be added).
3526       * @return This object.
3527       * @see #headers()
3528       */
3529      @Override
3530      public SELF mediaType(MediaType value) {
3531         super.mediaType(value);
3532         return headers(Accept.of(value), ContentType.of(value));
3533      }
3534
3535      /**
3536       * Appends the <c>Accept</c> and <c>Content-Type</c> headers on all requests made by this client.
3537       *
3538       * <p>
3539       * Headers are appended to the end of the current header list.
3540       *
3541       * <p>
3542       * This is a shortcut for calling <c>headerData().append(Accept.<jsm>of</jsm>(<jv>value</jv>), ContentType.<jsm>of</jsm>(<jv>value</jv>))</c>.
3543       *
3544       * @param value The new header values.
3545       *    <br>Can be <jk>null</jk> (no Accept or Content-Type headers will be added).
3546       * @return This object.
3547       * @see #headers()
3548       */
3549      public SELF mediaType(String value) {
3550         super.mediaType(MediaType.of(value));
3551         return headers(Accept.of(value), ContentType.of(value));
3552      }
3553
3554      /**
3555       * Convenience method for specifying BSON as the marshalling transmission media type.
3556       *
3557       * <p>
3558       * BSON (Binary JSON) is the format used by MongoDB. Identical to calling
3559       * <c>serializer(BsonSerializer.<jk>class</jk>).parser(BsonParser.<jk>class</jk>)</c>.
3560       *
3561       * @return This object.
3562       */
3563      public SELF bson() {
3564         return serializer(BsonSerializer.class).parser(BsonParser.class);
3565      }
3566
3567      /**
3568       * Convenience method for specifying MessagePack as the marshalling transmission media type.
3569       *
3570       * <p>
3571       * MessagePack is a binary equivalent to JSON that takes up considerably less space than JSON.
3572       *
3573       * <p>
3574       *    {@link MsgPackSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
3575       *    <ul>
3576       *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link #sortCollections()}) or
3577       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
3578       *    </ul>
3579       * <p>
3580       *    {@link MsgPackParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
3581       *    <ul>
3582       *       <li>The parser can be configured using any of the parser property setters (e.g. {@link #ignoreUnknownBeanProperties()}) or
3583       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
3584       *    </ul>
3585       * <p>
3586       *    <c>Accept</c> request header will be set to <js>"application/msgpack"</js> unless overridden
3587       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
3588       * <p>
3589       *    <c>Content-Type</c> request header will be set to <js>"application/msgpack"</js> unless overridden
3590       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
3591       * <p>
3592       *    Can be combined with other marshaller setters such as {@link #json()} to provide support for multiple languages.
3593       *    <ul>
3594       *       <li>When multiple languages are supported, the <c>Accept</c> and <c>Content-Type</c> headers control which marshallers are used, or uses the
3595       *       last-enabled language if the headers are not set.
3596       *    </ul>
3597       * <p>
3598       *    Identical to calling <c>serializer(MsgPackSerializer.<jk>class</jk>).parser(MsgPackParser.<jk>class</jk>)</c>.
3599       *
3600       * <h5 class='section'>Example:</h5>
3601       * <p class='bjava'>
3602       *    <jc>// Construct a client that uses MessagePack marshalling.</jc>
3603       *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().msgPack().build();
3604       * </p>
3605       *
3606       * @return This object.
3607       */
3608      public SELF msgPack() {
3609         return serializer(MsgPackSerializer.class).parser(MsgPackParser.class);
3610      }
3611
3612      /**
3613       * When called, <c>No-Trace: true</c> is added to requests.
3614       *
3615       * <p>
3616       * This gives the opportunity for the servlet to not log errors on invalid requests.
3617       * This is useful for testing purposes when you don't want your log file to show lots of errors that are simply the
3618       * results of testing.
3619       *
3620       * <p>
3621       * It's up to the server to decide whether to allow for this.
3622       * The <c>BasicTestRestLogger</c> class watches for this header and prevents logging of status 400+ responses to
3623       * prevent needless logging of test scenarios.
3624       *
3625       * @return This object.
3626       * @see #headers()
3627       */
3628      public SELF noTrace() {
3629         return headers(NoTrace.of(true));
3630      }
3631
3632      /**
3633       * <i><l>OpenApiCommon</l> configuration property:&emsp;</i>  Default collection format for HTTP parts.
3634       *
3635       * <p>
3636       * Specifies the collection format to use for HTTP parts when not otherwise specified via {@link Schema#collectionFormat()} for the
3637       * OpenAPI serializer and parser on this client.
3638       *
3639       * <h5 class='section'>Example:</h5>
3640       * <p class='bjava'>
3641       *    <jc>// Create a REST client with CSV format for http parts.</jc>
3642       *    RestClient <jv>client</jv> = RestClient
3643       *       .<jsm>create</jsm>()
3644       *       .collectionFormat(<jsf>CSV</jsf>)
3645       *       .build();
3646       *
3647       *    <jc>// An arbitrary data structure.</jc>
3648       *    AList <jv>list</jv> = AList.<jsm>of</jsm>(
3649       *       <js>"foo"</js>,
3650       *       <js>"bar"</js>,
3651       *       AMap.<jsm>of</jsm>(
3652       *          <js>"baz"</js>, AList.<jsm>of</jsm>(<js>"qux"</js>,<js>"true"</js>,<js>"123"</js>)
3653       *    )
3654       * );
3655       *
3656       *    <jc>// Set a header with a comma-separated list.</jc>
3657       *    <jv>client</jv>
3658       *       .get(<js>"/uri"</js>)
3659       *       .header(<js>"Foo"</js>, <jv>list</jv>)  <jc>// Will be serialized as: foo=bar,baz=qux\,true\,123</jc>
3660       *       .run();
3661       * </p>
3662       *
3663       * <ul class='values javatree'>
3664       *    <li class='jc'>{@link HttpPartCollectionFormat}
3665       *    <ul>
3666       *       <li class='jf'>{@link HttpPartCollectionFormat#CSV CSV} - (default) Comma-separated values (e.g. <js>"foo,bar"</js>).
3667       *       <li class='jf'>{@link HttpPartCollectionFormat#SSV SSV} - Space-separated values (e.g. <js>"foo bar"</js>).
3668       *       <li class='jf'>{@link HttpPartCollectionFormat#TSV TSV} - Tab-separated values (e.g. <js>"foo\tbar"</js>).
3669       *       <li class='jf'>{@link HttpPartCollectionFormat#PIPES PIPES} - Pipe-separated values (e.g. <js>"foo|bar"</js>).
3670       *       <li class='jf'>{@link HttpPartCollectionFormat#MULTI MULTI} - Corresponds to multiple parameter instances instead of multiple values for a single instance (e.g. <js>"foo=bar&amp;foo=baz"</js>).
3671       *       <li class='jf'>{@link HttpPartCollectionFormat#UONC UONC} - UON collection notation (e.g. <js>"@(foo,bar)"</js>).
3672       *    </ul>
3673       * </ul>
3674       *
3675       * <h5 class='section'>See Also:</h5><ul>
3676       *    <li class='jm'>{@link org.apache.juneau.marshall.oapi.OpenApiSerializer.Builder#collectionFormat(HttpPartCollectionFormat) OpenApiSerializer.Builder#collectionFormat(HttpPartCollectionFormat)}
3677       *    <li class='jm'>{@link org.apache.juneau.marshall.oapi.OpenApiParser.Builder#collectionFormat(HttpPartCollectionFormat) OpenApiParser.Builder#collectionFormat(HttpPartCollectionFormat)}
3678       * </ul>
3679       *
3680       * @param value
3681       *    The new value for this property.
3682       *    <br>The default value is {@link HttpPartCollectionFormat#NO_COLLECTION_FORMAT}.
3683       *    <br>Cannot be <jk>null</jk>.
3684       * @return This object.
3685       */
3686      public SELF oapiCollectionFormat(HttpPartCollectionFormat value) {
3687         serializers().forEach(OpenApiSerializer.Builder.class, x -> x.collectionFormat(value));
3688         parsers().forEach(OpenApiParser.Builder.class, x -> x.collectionFormat(value));
3689         partSerializer().builder(OpenApiSerializer.Builder.class, x -> x.collectionFormat(value));
3690         partParser().builder(OpenApiParser.Builder.class, x -> x.collectionFormat(value));
3691         return self();
3692      }
3693
3694      /**
3695       * <i><l>OpenApiCommon</l> configuration property:&emsp;</i>  Default OpenAPI format for HTTP parts.
3696       *
3697       * <p>
3698       * Specifies the format to use for HTTP parts when not otherwise specified via {@link Schema#format()} for
3699       * the OpenAPI serializer and parser on this client.
3700       *
3701       * <h5 class='section'>Example:</h5>
3702       * <p class='bjava'>
3703       *    <jc>// Create a REST client with UON part serialization and parsing.</jc>
3704       *    RestClient <jv>client</jv>  = RestClient
3705       *       .<jsm>create</jsm>()
3706       *       .oapiFormat(<jsf>UON</jsf>)
3707       *       .build();
3708       *
3709       *    <jc>// Set a header with a value in UON format.</jc>
3710       *    <jv>client</jv>
3711       *       .get(<js>"/uri"</js>)
3712       *       .header(<js>"Foo"</js>, <js>"bar baz"</js>)  <jc>// Will be serialized as:  'bar baz'</jc>
3713       *       .run();
3714       * </p>
3715       *
3716       * <ul class='values javatree'>
3717       *    <li class='jc'>{@link HttpPartFormat}
3718       *    <ul>
3719       *       <li class='jf'>{@link HttpPartFormat#UON UON} - UON notation (e.g. <js>"'foo bar'"</js>).
3720       *       <li class='jf'>{@link HttpPartFormat#INT32 INT32} - Signed 32 bits.
3721       *       <li class='jf'>{@link HttpPartFormat#INT64 INT64} - Signed 64 bits.
3722       *       <li class='jf'>{@link HttpPartFormat#FLOAT FLOAT} - 32-bit floating point number.
3723       *       <li class='jf'>{@link HttpPartFormat#DOUBLE DOUBLE} - 64-bit floating point number.
3724       *       <li class='jf'>{@link HttpPartFormat#BYTE BYTE} - BASE-64 encoded characters.
3725       *       <li class='jf'>{@link HttpPartFormat#BINARY BINARY} - Hexadecimal encoded octets (e.g. <js>"00FF"</js>).
3726       *       <li class='jf'>{@link HttpPartFormat#BINARY_SPACED BINARY_SPACED} - Spaced-separated hexadecimal encoded octets (e.g. <js>"00 FF"</js>).
3727       *       <li class='jf'>{@link HttpPartFormat#DATE DATE} - An <a href='http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14'>RFC3339 full-date</a>.
3728       *       <li class='jf'>{@link HttpPartFormat#DATE_TIME DATE_TIME} - An <a href='http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14'>RFC3339 date-time</a>.
3729       *       <li class='jf'>{@link HttpPartFormat#PASSWORD PASSWORD} - Used to hint UIs the input needs to be obscured.
3730       *       <li class='jf'>{@link HttpPartFormat#NO_FORMAT NO_FORMAT} - (default) Not specified.
3731       *    </ul>
3732       * </ul>
3733       *
3734       * <h5 class='section'>See Also:</h5><ul>
3735       *    <li class='jm'>{@link org.apache.juneau.marshall.oapi.OpenApiSerializer.Builder#format(HttpPartFormat) OpenApiSerializer.Builder#format(HttpPartFormat)}
3736       *    <li class='jm'>{@link org.apache.juneau.marshall.oapi.OpenApiParser.Builder#format(HttpPartFormat) OpenApiParser.Builder#format(HttpPartFormat)}
3737       * </ul>
3738       *
3739       * @param value
3740       *    The new value for this property.
3741       *    <br>The default value is {@link HttpPartFormat#NO_FORMAT}.
3742       *    <br>Cannot be <jk>null</jk>.
3743       * @return This object.
3744       */
3745      public SELF oapiFormat(HttpPartFormat value) {
3746         serializers().forEach(OpenApiSerializer.Builder.class, x -> x.format(value));
3747         parsers().forEach(OpenApiParser.Builder.class, x -> x.format(value));
3748         partSerializer().builder(OpenApiSerializer.Builder.class).ifPresent(x -> x.format(value));
3749         partParser().builder(OpenApiParser.Builder.class).ifPresent(x -> x.format(value));
3750         return self();
3751      }
3752
3753      /**
3754       * Convenience method for specifying OpenAPI as the marshalling transmission media type.
3755       *
3756       * <p>
3757       * OpenAPI is a language that allows serialization to formats that use {@link HttpPartSchema} objects to describe their structure.
3758       *
3759       * <p>
3760       *    {@link OpenApiSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
3761       *    <ul>
3762       *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link #sortCollections()}) or
3763       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
3764       *       <li>Typically the {@link RestRequest#content(Object, HttpPartSchema)} method will be used to specify the body of the request with the
3765       *          schema describing it's structure.
3766       *    </ul>
3767       * <p>
3768       *    {@link OpenApiParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
3769       *    <ul>
3770       *       <li>The parser can be configured using any of the parser property setters (e.g. {@link #ignoreUnknownBeanProperties()}) or
3771       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
3772       *       <li>Typically the {@link ResponseContent#schema(HttpPartSchema)} method will be used to specify the structure of the response body.
3773       *    </ul>
3774       * <p>
3775       *    <c>Accept</c> request header will be set to <js>"text/openapi"</js> unless overridden
3776       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
3777       * <p>
3778       *    <c>Content-Type</c> request header will be set to <js>"text/openapi"</js> unless overridden
3779       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
3780       * <p>
3781       *    Can be combined with other marshaller setters such as {@link #json()} to provide support for multiple languages.
3782       *    <ul>
3783       *       <li>When multiple languages are supported, the <c>Accept</c> and <c>Content-Type</c> headers control which marshallers are used, or uses the
3784       *       last-enabled language if the headers are not set.
3785       *    </ul>
3786       * <p>
3787       *    Identical to calling <c>serializer(OpenApiSerializer.<jk>class</jk>).parser(OpenApiParser.<jk>class</jk>)</c>.
3788       *
3789       * <h5 class='section'>Example:</h5>
3790       * <p class='bjava'>
3791       *    <jc>// Construct a client that uses OpenAPI marshalling.</jc>
3792       *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().openApi().build();
3793       * </p>
3794       *
3795       * @return This object.
3796       */
3797      public SELF openApi() {
3798         return serializer(OpenApiSerializer.class).parser(OpenApiParser.class);
3799      }
3800
3801      /**
3802       * <i><l>UonSerializer</l> configuration property:&emsp;</i>  Parameter format.
3803       *
3804       * <p>
3805       * Specifies the format of parameters when using the {@link UrlEncodingSerializer} to serialize Form Posts.
3806       *
3807       * <p>
3808       * Specifies the format to use for GET parameter keys and values.
3809       *
3810       * <h5 class='section'>Example:</h5>
3811       * <p class='bjava'>
3812       *    <jc>// Create a REST client with URL-Encoded serializer that serializes values in plain-text format.</jc>
3813       *    RestClient <jv>client</jv> = RestClient
3814       *       .<jsm>create</jsm>()
3815       *       .urlEnc()
3816       *       .paramFormat(<jsf>PLAINTEXT</jsf>)
3817       *       .build();
3818       *
3819       *    <jc>// An arbitrary data structure.</jc>
3820       *    AMap <jv>map</jv> = AMap.<jsm>of</jsm>(
3821       *       <js>"foo"</js>, <js>"bar"</js>,
3822       *       <js>"baz"</js>, <jk>new</jk> String[]{<js>"qux"</js>, <js>"true"</js>, <js>"123"</js>}
3823       *    );
3824       *
3825       *    <jc>// Request body will be serialized as:  foo=bar,baz=qux,true,123</jc>
3826       *    <jv>client</jv>
3827       *       .post(<js>"/uri"</js>, <jv>map</jv>)
3828       *       .run();
3829       * </p>
3830       *
3831       * <ul class='values javatree'>
3832       *    <li class='jf'>{@link ParamFormat#UON} (default) - Use UON notation for parameters.
3833       *    <li class='jf'>{@link ParamFormat#PLAINTEXT} - Use plain text for parameters.
3834       * </ul>
3835       *
3836       * <h5 class='section'>See Also:</h5><ul>
3837       *    <li class='jm'>{@link org.apache.juneau.marshall.uon.UonSerializer.Builder#paramFormat(ParamFormat) UonSerializer.Builder#paramFormat(ParamFormat)}
3838       * </ul>
3839       *
3840       * @param value The new value for this property.
3841       *    <br>Cannot be <jk>null</jk>.
3842       * @return This object.
3843       */
3844      public SELF paramFormat(ParamFormat value) {
3845         serializers().forEach(UonSerializer.Builder.class, x -> x.paramFormat(value));
3846         return self();
3847      }
3848
3849      /**
3850       * <i><l>UonSerializer</l> configuration property:&emsp;</i>  Parameter format.
3851       *
3852       * <p>
3853       * Specifies the format of parameters when using the {@link UrlEncodingSerializer} to serialize Form Posts.
3854       *
3855       * <p>
3856       * Specifies plaintext as the format to use for GET parameter keys and values.
3857       *
3858       * <h5 class='section'>Example:</h5>
3859       * <p class='bjava'>
3860       *    <jc>// Create a REST client with URL-Encoded serializer that serializes values in plain-text format.</jc>
3861       *    RestClient <jv>client</jv> = RestClient
3862       *       .<jsm>create</jsm>()
3863       *       .urlEnc()
3864       *       .build();
3865       *
3866       *    <jc>// An arbitrary data structure.</jc>
3867       *    AMap <jv>map</jv> = AMap.<jsm>of</jsm>(
3868       *       <js>"foo"</js>, <js>"bar"</js>,
3869       *       <js>"baz"</js>, <jk>new</jk> String[]{<js>"qux"</js>, <js>"true"</js>, <js>"123"</js>}
3870       *    );
3871       *
3872       *    <jc>// Request body will be serialized as:  foo=bar,baz=qux,true,123</jc>
3873       *    <jv>client</jv>
3874       *       .post(<js>"/uri"</js>, <jv>map</jv>)
3875       *       .run();
3876       * </p>
3877       *
3878       * <h5 class='section'>See Also:</h5><ul>
3879       *    <li class='jm'>{@link org.apache.juneau.marshall.uon.UonSerializer.Builder#paramFormatPlain() UonSerializer.Builder#paramFormatPlain()}
3880       * </ul>
3881       *
3882       * @return This object.
3883       */
3884      public SELF paramFormatPlain() {
3885         serializers().forEach(UonSerializer.Builder.class, UonSerializer.Builder::paramFormatPlain);
3886         return self();
3887      }
3888
3889      /**
3890       * Parser.
3891       *
3892       * <p>
3893       * Associates the specified {@link Parser Parser} with the HTTP client.
3894       *
3895       * <p>
3896       * The parser is used to parse the HTTP response body into a POJO.
3897       *
3898       * <h5 class='section'>Notes:</h5><ul>
3899       *    <li class='note'>When using this method that takes in a class, the parser can be configured using any of the parser property setters (e.g. {@link #ignoreUnknownBeanProperties()}) or
3900       *    bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
3901       * </ul>
3902       *
3903       * <h5 class='section'>Example:</h5>
3904       * <p class='bjava'>
3905       *    <jc>// Create a client that uses JSON transport for response bodies.</jc>
3906       *    RestClient <jv>client</jv> = RestClient
3907       *       .<jsm>create</jsm>()
3908       *       .parser(JsonParser.<jk>class</jk>)
3909       *       .build();
3910       * </p>
3911       *
3912       * @param value
3913       *    The new value for this setting.
3914       *    <br>The default value is {@link JsonParser#DEFAULT}.
3915       * @return This object.
3916       */
3917      public SELF parser(Class<? extends Parser> value) {
3918         return parsers(value);
3919      }
3920
3921      /**
3922       * Parser.
3923       *
3924       * <p>
3925       * Associates the specified {@link Parser Parser} with the HTTP client.
3926       *
3927       * <p>
3928       * The parser is used to parse the HTTP response body into a POJO.
3929       *
3930       * <h5 class='section'>Notes:</h5><ul>
3931       *    <li class='note'>When using this method that takes in a pre-instantiated parser, the parser property setters (e.g. {@link #ignoreUnknownBeanProperties()}) or
3932       *    bean context property setters (e.g. {@link #swaps(Class...)}) defined
3933       *    on this builder class have no effect.
3934       * </ul>
3935       *
3936       * <h5 class='section'>Example:</h5>
3937       * <p class='bjava'>
3938       *    <jc>// Create a client that uses a predefined JSON parser for response bodies.</jc>
3939       *    RestClient <jv>client</jv> = RestClient
3940       *       .<jsm>create</jsm>()
3941       *       .parser(JsonParser.<jsf>DEFAULT</jsf>)
3942       *       .build();
3943       * </p>
3944       *
3945       * @param value
3946       *    The new value for this setting.
3947       *    <br>The default value is {@link JsonParser#DEFAULT}.
3948       *    <br>Cannot be <jk>null</jk>.
3949       * @return This object.
3950       */
3951      public SELF parser(Parser value) {
3952         return parsers(value);
3953      }
3954
3955      /**
3956       * Returns the parser group sub-builder.
3957       *
3958       * @return The parser group sub-builder.
3959       */
3960      public final ParserSet.Builder parsers() {
3961         if (parsers == null)
3962            parsers = createParsers();
3963         return parsers;
3964      }
3965
3966      /**
3967       * Parsers.
3968       *
3969       * <p>
3970       * Associates the specified {@link Parser Parsers} with the HTTP client.
3971       *
3972       * <p>
3973       * The parsers are used to parse the HTTP response body into a POJO.
3974       *
3975       * <p>
3976       * The parser that best matches the <c>Accept</c> header will be used to parse the response body.
3977       * <br>If no <c>Accept</c> header is specified, the first parser in the list will be used.
3978       *
3979       * <h5 class='section'>Notes:</h5><ul>
3980       *    <li class='note'>When using this method that takes in classes, the parsers can be configured using any of the parser property setters (e.g. {@link #ignoreUnknownBeanProperties()}) or
3981       *    bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
3982       * </ul>
3983       *
3984       * <h5 class='section'>Example:</h5>
3985       * <p class='bjava'>
3986       *    <jc>// Create a client that uses JSON and XML transport for response bodies.</jc>
3987       *    RestClient <jv>client</jv> = RestClient
3988       *       .<jsm>create</jsm>()
3989       *       .parser(JsonParser.<jk>class</jk>, XmlParser.<jk>class</jk>)
3990       *       .build();
3991       * </p>
3992       *
3993       * @param value
3994       *    The new value for this setting.
3995       *    <br>The default value is {@link JsonParser#DEFAULT}.
3996       * @return This object.
3997       */
3998      public SELF parsers(Class<? extends Parser>...value) {
3999         reqnns("value", value);
4000         parsers().add(value);
4001         return self();
4002      }
4003
4004      /**
4005       * Parsers.
4006       *
4007       * <p>
4008       * Associates the specified {@link Parser Parsers} with the HTTP client.
4009       *
4010       * <p>
4011       * The parsers are used to parse the HTTP response body into a POJO.
4012       *
4013       * <p>
4014       * The parser that best matches the <c>Accept</c> header will be used to parse the response body.
4015       * <br>If no <c>Accept</c> header is specified, the first parser in the list will be used.
4016       *
4017       * <h5 class='section'>Notes:</h5><ul>
4018       *    <li class='note'>When using this method that takes in pre-instantiated parsers, the parser property setters (e.g. {@link #ignoreUnknownBeanProperties()}) or
4019       *    bean context property setters (e.g. {@link #swaps(Class...)}) defined
4020       *    on this builder class have no effect.
4021       * </ul>
4022       *
4023       * <h5 class='section'>Example:</h5>
4024       * <p class='bjava'>
4025       *    <jc>// Create a client that uses JSON and XML transport for response bodies.</jc>
4026       *    RestClient <jv>client</jv> = RestClient
4027       *       .<jsm>create</jsm>()
4028       *       .parser(JsonParser.<jsf>DEFAULT</jsf>, XmlParser.<jsf>DEFAULT</jsf>)
4029       *       .build();
4030       * </p>
4031       *
4032       * @param value
4033       *    The new value for this setting.
4034       *    <br>The default value is {@link JsonParser#DEFAULT}.
4035       * @return This object.
4036       */
4037      public SELF parsers(Parser...value) {
4038         reqnns("value", value);
4039         parsers().add(value);
4040         return self();
4041      }
4042
4043      /**
4044       * Returns the part parser sub-builder.
4045       *
4046       * @return The part parser sub-builder.
4047       */
4048      public final HttpPartParser.Creator partParser() {
4049         if (partParser == null)
4050            partParser = createPartParser();
4051         return partParser;
4052      }
4053
4054      /**
4055       * Part parser.
4056       *
4057       * <p>
4058       * The parser to use for parsing POJOs from form data, query parameters, headers, and path variables.
4059       *
4060       * <p>
4061       * The default part parser is {@link OpenApiParser} which allows for schema-driven marshalling.
4062       *
4063       * <h5 class='section'>Example:</h5>
4064       * <p class='bjava'>
4065       *    <jc>// Create a client that uses UON format by default for incoming HTTP parts.</jc>
4066       *    RestClient <jv>client</jv> = RestClient
4067       *       .<jsm>create</jsm>()
4068       *       .partParser(UonParser.<jk>class</jk>)
4069       *       .build();
4070       * </p>
4071       *
4072       * @param value
4073       *    The new value for this setting.
4074       *    <br>The default value is {@link OpenApiParser}.
4075       *    <br>Cannot be <jk>null</jk>.
4076       * @return This object.
4077       */
4078      public SELF partParser(Class<? extends HttpPartParser> value) {
4079         partParser().type(reqnn("value", value));
4080         return self();
4081      }
4082
4083      /**
4084       * Part parser.
4085       *
4086       * <p>
4087       * The parser to use for parsing POJOs from form data, query parameters, headers, and path variables.
4088       *
4089       * <p>
4090       * The default part parser is {@link OpenApiParser} which allows for schema-driven marshalling.
4091       *
4092       * <h5 class='section'>Example:</h5>
4093       * <p class='bjava'>
4094       *    <jc>// Create a client that uses UON format by default for incoming HTTP parts.</jc>
4095       *    RestClient <jv>client</jv> = RestClient
4096       *       .<jsm>create</jsm>()
4097       *       .partParser(UonParser.<jsf>DEFAULT</jsf>)
4098       *       .build();
4099       * </p>
4100       *
4101       * @param value
4102       *    The new value for this setting.
4103       *    <br>The default value is {@link OpenApiParser}.
4104       *    <br>Cannot be <jk>null</jk>.
4105       * @return This object.
4106       */
4107      public SELF partParser(HttpPartParser value) {
4108         partParser().impl(reqnn("value", value));
4109         return self();
4110      }
4111
4112      /**
4113       * Returns the part serializer sub-builder.
4114       *
4115       * @return The part serializer sub-builder.
4116       */
4117      public final HttpPartSerializer.Creator partSerializer() {
4118         if (partSerializer == null)
4119            partSerializer = createPartSerializer();
4120         return partSerializer;
4121      }
4122
4123      /**
4124       * Part serializer.
4125       *
4126       * <p>
4127       * The serializer to use for serializing POJOs in form data, query parameters, headers, and path variables.
4128       *
4129       * <p>
4130       * The default part serializer is {@link OpenApiSerializer} which allows for schema-driven marshalling.
4131       *
4132       * <h5 class='section'>Example:</h5>
4133       * <p class='bjava'>
4134       *    <jc>// Create a client that uses UON format by default for outgoing HTTP parts.</jc>
4135       *    RestClient <jv>client</jv> = RestClient
4136       *       .<jsm>create</jsm>()
4137       *       .partSerializer(UonSerializer.<jk>class</jk>)
4138       *       .build();
4139       * </p>
4140       *
4141       * @param value
4142       *    The new value for this setting.
4143       *    <br>The default value is {@link OpenApiSerializer}.
4144       *    <br>Cannot be <jk>null</jk>.
4145       * @return This object.
4146       */
4147      public SELF partSerializer(Class<? extends HttpPartSerializer> value) {
4148         partSerializer().type(reqnn("value", value));
4149         return self();
4150      }
4151
4152      /**
4153       * Part serializer.
4154       *
4155       * <p>
4156       * The serializer to use for serializing POJOs in form data, query parameters, headers, and path variables.
4157       *
4158       * <p>
4159       * The default part serializer is {@link OpenApiSerializer} which allows for schema-driven marshalling.
4160       *
4161       * <h5 class='section'>Example:</h5>
4162       * <p class='bjava'>
4163       *    <jc>// Create a client that uses UON format by default for outgoing HTTP parts.</jc>
4164       *    RestClient <jv>client</jv> = RestClient
4165       *       .<jsm>create</jsm>()
4166       *       .partSerializer(UonSerializer.<jsf>DEFAULT</jsf>)
4167       *       .build();
4168       * </p>
4169       *
4170       * @param value
4171       *    The new value for this setting.
4172       *    <br>The default value is {@link OpenApiSerializer}.
4173       *    <br>Cannot be <jk>null</jk>.
4174       * @return This object.
4175       */
4176      public SELF partSerializer(HttpPartSerializer value) {
4177         partSerializer().impl(reqnn("value", value));
4178         return self();
4179      }
4180
4181      /**
4182       * Returns the builder for the list of path data parameters that get applied to all requests created by this builder.
4183       *
4184       * <p>
4185       * This is the primary method for accessing the path data parameter list.
4186       * On first call, the builder is created via the method {@link #createFormData()}.
4187       *
4188       * <h5 class='section'>Example:</h5>
4189       * <p class='bjava'>
4190       *    <jc>// Create a client that uses "bar" for the "{foo}" path variable on every request.</jc>
4191       *    RestClient.Builder&lt;?&gt; <jv>builder</jv> = RestClient.<jsm>create</jsm>();
4192       *    <jv>builder</jv>.pathData().setDefault(<js>"foo"</js>, <js>"bar"</js>));
4193       *    RestClient <jv>client</jv> = <jv>builder</jv>.build();
4194       * </p>
4195       *
4196       * <p>
4197       * The following convenience methods are also provided for updating the parameters:
4198       * <ul>
4199       *    <li class='jm'>{@link #pathData(NameValuePair...)}
4200       *    <li class='jm'>{@link #pathDataDefault(NameValuePair...)}
4201       *    <li class='jm'>{@link #pathData(String,String)}
4202       *    <li class='jm'>{@link #pathData(String,Supplier)}
4203       * </ul>
4204       *
4205       * @return The form data list builder.
4206       */
4207      public final PartList pathData() {
4208         if (pathData == null)
4209            pathData = createPathData();
4210         return pathData;
4211      }
4212
4213      /**
4214       * Sets multiple path parameters on all requests.
4215       *
4216       * <h5 class='section'>Example:</h5>
4217       * <p class='bjava'>
4218       *    <jk>import static</jk> org.apache.juneau.http.HttpParts.*;
4219       *
4220       *    RestClient <jv>client</jv> = RestClient
4221       *       .<jsm>create</jsm>()
4222       *       .pathData(
4223       *          <jsm>stringPart</jsm>(<js>"foo"</js>, <js>"bar"</js>),
4224       *          <jsm>booleanPart</jsm>(<js>"baz"</js>, <jk>true</jk>)
4225       *       )
4226       *       .build();
4227       * </p>
4228       *
4229       * <p>
4230       * This is a shortcut for calling <c>pathData().append(<jv>parts</jv>)</c>.
4231       *
4232       * @param parts
4233       *    The path parameters.
4234       *    <br>Can contain <jk>null</jk> values (ignored).
4235       * @return This object.
4236       * @see #pathData()
4237       */
4238      public SELF pathData(NameValuePair...parts) {
4239         pathData().append(parts);
4240         return self();
4241      }
4242
4243      /**
4244       * Appends a path parameter to all request bodies.
4245       *
4246       * <h5 class='section'>Example:</h5>
4247       * <p class='bjava'>
4248       *    RestClient <jv>client</jv> = RestClient
4249       *       .<jsm>create</jsm>()
4250       *       .pathData(<js>"foo"</js>, <js>"bar"</js>)
4251       *       .build();
4252       * </p>
4253       *
4254       * <p>
4255       * This is a shortcut for calling <c>pathData().append(<jv>name</jv>,<jv>value</jv>)</c>.
4256       *
4257       * @param name The parameter name.
4258       *    <br>Cannot be <jk>null</jk>.
4259       * @param value The parameter value.
4260       *    <br>Can be <jk>null</jk> (null value will be serialized).
4261       * @return This object.
4262       * @see #pathData()
4263       */
4264      public SELF pathData(String name, String value) {
4265         pathData().append(name, value);
4266         return self();
4267      }
4268
4269      /**
4270       * Sets a path parameter with a dynamic value to all request bodies.
4271       *
4272       * <h5 class='section'>Example:</h5>
4273       * <p class='bjava'>
4274       *    RestClient <jv>client</jv> = RestClient
4275       *       .<jsm>create</jsm>()
4276       *       .pathData(<js>"foo"</js>, ()-&gt;<js>"bar"</js>)
4277       *       .build();
4278       * </p>
4279       *
4280       * <p>
4281       * This is a shortcut for calling <c>pathData().append(<jv>name</jv>,<jv>value</jv>)</c>.
4282       *
4283       * @param name The parameter name.
4284       *    <br>Cannot be <jk>null</jk>.
4285       * @param value The parameter value supplier.
4286       *    <br>Can be <jk>null</jk> (null value will be serialized).
4287       * @return This object.
4288       * @see #pathData()
4289       */
4290      public SELF pathData(String name, Supplier<String> value) {
4291         pathData().set(name, value);
4292         return self();
4293      }
4294
4295      /**
4296       * Sets default path parameter values.
4297       *
4298       * <p>
4299       * Uses default values for specified parameters if not otherwise specified on the outgoing requests.
4300       *
4301       * <h5 class='section'>Example:</h5>
4302       * <p class='bjava'>
4303       *    RestClient <jv>client</jv> = RestClient
4304       *       .<jsm>create</jsm>()
4305       *       .pathDataDefault(<jsm>stringPart</jsm>(<js>"foo"</js>, ()-&gt;<js>"bar"</js>));
4306       *       .build();
4307       * </p>
4308       *
4309       * <p>
4310       * This is a shortcut for calling <c>pathData().setDefault(<jv>parts</jv>)</c>.
4311       *
4312       * @param parts The parts.
4313       *    <br>Can contain <jk>null</jk> values (ignored).
4314       * @return This object.
4315       * @see #pathData()
4316       */
4317      public SELF pathDataDefault(NameValuePair...parts) {
4318         pathData().setDefault(parts);
4319         return self();
4320      }
4321
4322      /**
4323       * Convenience method for specifying Plain Text as the marshalling transmission media type.
4324       *
4325       * <p>
4326       * Plain text marshalling typically only works on simple POJOs that can be converted to and from strings using
4327       * swaps, swap methods, etc...
4328       *
4329       * <p>
4330       *    {@link PlainTextSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
4331       *    <ul>
4332       *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link #sortCollections()}) or
4333       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
4334       *    </ul>
4335       * <p>
4336       *    {@link PlainTextParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
4337       *    <ul>
4338       *       <li>The parser can be configured using any of the parser property setters (e.g. {@link #ignoreUnknownBeanProperties()}) or
4339       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
4340       *    </ul>
4341       * <p>
4342       *    <c>Accept</c> request header will be set to <js>"text/plain"</js> unless overridden
4343       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
4344       * <p>
4345       *    <c>Content-Type</c> request header will be set to <js>"text/plain"</js> unless overridden
4346       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
4347       * <p>
4348       *    Can be combined with other marshaller setters such as {@link #json()} to provide support for multiple languages.
4349       *    <ul>
4350       *       <li>When multiple languages are supported, the <c>Accept</c> and <c>Content-Type</c> headers control which marshallers are used, or uses the
4351       *       last-enabled language if the headers are not set.
4352       *    </ul>
4353       * <p>
4354       *    Identical to calling <c>serializer(PlainTextSerializer.<jk>class</jk>).parser(PlainTextParser.<jk>class</jk>)</c>.
4355       *
4356       * <h5 class='section'>Example:</h5>
4357       * <p class='bjava'>
4358       *    <jc>// Construct a client that uses Plain Text marshalling.</jc>
4359       *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().plainText().build();
4360       * </p>
4361       *
4362       * @return This object.
4363       */
4364      public SELF plainText() {
4365         return serializer(PlainTextSerializer.class).parser(PlainTextParser.class);
4366      }
4367
4368      /**
4369       * When called, the {@link #createConnectionManager()} method will return a {@link PoolingHttpClientConnectionManager}
4370       * instead of a {@link BasicHttpClientConnectionManager}.
4371       *
4372       * <h5 class='section'>Example:</h5>
4373       * <p class='bjava'>
4374       *    <jc>// Construct a client that uses pooled connections.</jc>
4375       *    RestClient <jv>client</jv> = RestClient
4376       *       .<jsm>create</jsm>()
4377       *       .pooled()
4378       *       .build();
4379       * </p>
4380       *
4381       * @return This object.
4382       */
4383      public SELF pooled() {
4384         this.pooled = true;
4385         return self();
4386      }
4387
4388      /**
4389       * Assigns default proxy value.
4390       *
4391       * <h5 class='section'>Notes:</h5><ul>
4392       *    <li class='note'>This value can be overridden by the {@link #routePlanner(HttpRoutePlanner)} method.
4393       *    <li class='warn'>Through a proxy, the SSRF guard's pin-on-connect would check the proxy's address rather than
4394       *       the target's, so an SSRF-guard-active {@code @Remote} call (one without the
4395       *       {@link #allowPrivateUrls(boolean) allowPrivateUrls} opt-in) on a proxy route is refused.  This applies to any
4396       *       proxy route, including one chosen by a {@link #routePlanner(HttpRoutePlanner) route planner} or the proxy
4397       *       system properties ({@link #useSystemProperties()}).  Ordinary requests are unaffected.
4398       * </ul>
4399       *
4400       * @param proxy New property value.
4401       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
4402       * @return This object.
4403       * @see HttpClientBuilder#setProxy(HttpHost)
4404       */
4405      public SELF proxy(HttpHost proxy) {
4406         httpClientBuilder().setProxy(proxy);
4407         return self();
4408      }
4409
4410      /**
4411       * Assigns {@link AuthenticationStrategy} instance for proxy authentication.
4412       *
4413       * @param proxyAuthStrategy New property value.
4414       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
4415       * @return This object.
4416       * @see HttpClientBuilder#setProxyAuthenticationStrategy(AuthenticationStrategy)
4417       */
4418      public SELF proxyAuthenticationStrategy(AuthenticationStrategy proxyAuthStrategy) {
4419         httpClientBuilder().setProxyAuthenticationStrategy(proxyAuthStrategy);
4420         return self();
4421      }
4422
4423      /**
4424       * Assigns file containing public suffix matcher.
4425       *
4426       * <h5 class='section'>Notes:</h5><ul>
4427       *    <li class='note'>Instances of this class can be created with {@link PublicSuffixMatcherLoader}.
4428       *    <li class='note'>It is used for cookies and, in both pools of the connection manager the default
4429       *       {@link #createConnectionManager()} builds, by the default hostname verifier (one is used unless
4430       *       {@link #sslHostnameVerifier(HostnameVerifier)} or {@link #sslSocketFactory(LayeredConnectionSocketFactory)}
4431       *       is set).
4432       * </ul>
4433       *
4434       * @param publicSuffixMatcher New property value.
4435       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
4436       * @return This object.
4437       * @see HttpClientBuilder#setPublicSuffixMatcher(PublicSuffixMatcher)
4438       */
4439      public SELF publicSuffixMatcher(PublicSuffixMatcher publicSuffixMatcher) {
4440         this.publicSuffixMatcher = publicSuffixMatcher;
4441         httpClientBuilder().setPublicSuffixMatcher(publicSuffixMatcher);
4442         return self();
4443      }
4444
4445      /**
4446       * Returns the builder for the list of query parameters that get applied to all requests created by this builder.
4447       *
4448       * <p>
4449       * This is the primary method for accessing the query parameter list.
4450       * On first call, the builder is created via the method {@link #createQueryData()}.
4451       *
4452       * <h5 class='section'>Example:</h5>
4453       * <p class='bjava'>
4454       *    <jc>// Create a client that adds a "foo=bar" query parameter on every request.</jc>
4455       *    RestClient.Builder&lt;?&gt; <jv>builder</jv> = RestClient.<jsm>create</jsm>();
4456       *    <jv>builder</jv>.queryData().setDefault(<js>"foo"</js>, <js>"bar"</js>));
4457       *    RestClient <jv>client</jv> = <jv>builder</jv>.build();
4458       * </p>
4459       *
4460       * <p>
4461       * The following convenience methods are also provided for updating the parameters:
4462       * <ul>
4463       *    <li class='jm'>{@link #queryData(NameValuePair...)}
4464       *    <li class='jm'>{@link #queryDataDefault(NameValuePair...)}
4465       *    <li class='jm'>{@link #queryData(String,String)}
4466       *    <li class='jm'>{@link #queryData(String,Supplier)}
4467       * </ul>
4468       *
4469       * @return The query data list builder.
4470       */
4471      public final PartList queryData() {
4472         if (queryData == null)
4473            queryData = createQueryData();
4474         return queryData;
4475      }
4476
4477      /**
4478       * Appends multiple query parameters to the URI of all requests.
4479       *
4480       * <h5 class='section'>Example:</h5>
4481       * <p class='bjava'>
4482       *    <jk>import static</jk> org.apache.juneau.http.HttpParts.*;
4483       *
4484       *    RestClient <jv>client</jv> = RestClient
4485       *       .<jsm>create</jsm>()
4486       *       .queryData(
4487       *          <jsm>stringPart</jsm>(<js>"foo"</js>, <js>"bar"</js>),
4488       *          <jsm>booleanPart</jsm>(<js>"baz"</js>, <jk>true</jk>)
4489       *       )
4490       *       .build();
4491       * </p>
4492       *
4493       * <p>
4494       * This is a shortcut for calling <c>queryData().append(<jv>parts</jv>)</c>.
4495       *
4496       * @param parts
4497       *    The query parameters.
4498       *    <br>Can contain <jk>null</jk> values (ignored).
4499       * @return This object.
4500       * @see #queryData()
4501       */
4502      public SELF queryData(NameValuePair...parts) {
4503         queryData().append(parts);
4504         return self();
4505      }
4506
4507      /**
4508       * Appends a query parameter to the URI.
4509       *
4510       * <h5 class='section'>Example:</h5>
4511       * <p class='bjava'>
4512       *    RestClient <jv>client</jv> = RestClient
4513       *       .<jsm>create</jsm>()
4514       *       .queryData(<js>"foo"</js>, <js>"bar"</js>)
4515       *       .build();
4516       * </p>
4517       *
4518       * <p>
4519       * This is a shortcut for calling <c>queryData().append(<jv>name</jv>,<jv>value</jv>)</c>.
4520       *
4521       * @param name The parameter name.
4522       *    <br>Cannot be <jk>null</jk>.
4523       * @param value The parameter value.
4524       *    <br>Can be <jk>null</jk> (null value will be serialized).
4525       * @return This object.
4526       * @see #queryData()
4527       */
4528      public SELF queryData(String name, String value) {
4529         queryData().append(name, value);
4530         return self();
4531      }
4532
4533      /**
4534       * Appends a query parameter with a dynamic value to the URI.
4535       *
4536       * <h5 class='section'>Example:</h5>
4537       * <p class='bjava'>
4538       *    RestClient <jv>client</jv> = RestClient
4539       *       .<jsm>create</jsm>()
4540       *       .queryData(<js>"foo"</js>, ()-&gt;<js>"bar"</js>)
4541       *       .build();
4542       * </p>
4543       *
4544       * <p>
4545       * This is a shortcut for calling <c>queryData().append(<jv>name</jv>,<jv>value</jv>)</c>.
4546       *
4547       * @param name The parameter name.
4548       *    <br>Cannot be <jk>null</jk>.
4549       * @param value The parameter value supplier.
4550       *    <br>Can be <jk>null</jk> (null value will be serialized).
4551       * @return This object.
4552       * @see #queryData()
4553       */
4554      public SELF queryData(String name, Supplier<String> value) {
4555         queryData().append(name, value);
4556         return self();
4557      }
4558
4559      /**
4560       * Sets default query parameter values.
4561       *
4562       * <p>
4563       * Uses default values for specified parameters if not otherwise specified on the outgoing requests.
4564       *
4565       * <h5 class='section'>Example:</h5>
4566       * <p class='bjava'>
4567       *    RestClient <jv>client</jv> = RestClient
4568       *       .<jsm>create</jsm>()
4569       *       .queryDataDefault(<jsm>stringPart</jsm>(<js>"foo"</js>, ()-&gt;<js>"bar"</js>));
4570       *       .build();
4571       * </p>
4572       *
4573       * <p>
4574       * This is a shortcut for calling <c>queryData().setDefault(<jv>parts</jv>)</c>.
4575       *
4576       * @param parts The parts.
4577       *    <br>Can contain <jk>null</jk> values (ignored).
4578       * @return This object.
4579       * @see #queryData()
4580       */
4581      public SELF queryDataDefault(NameValuePair...parts) {
4582         queryData().setDefault(parts);
4583         return self();
4584      }
4585
4586      /**
4587       * Sets a default query parameter with serializer session options (UON map) for all requests.
4588       *
4589       * <p>
4590       * This is a shortcut for <c>queryDataDefault(stringPart({@link RestSharedConstants#QUERY_juneauSerializerOptions}, <jv>uon</jv>))</c>.
4591       *
4592       * @param uon
4593       *    Serializer session options in UON form.
4594       *    <br>Can be <jk>null</jk> (default is not set by this method).
4595       * @return This object.
4596       */
4597      public SELF serializerSessionOptionsQueryDefault(String uon) {
4598         if (uon != null)
4599            queryDataDefault(stringPart(QUERY_juneauSerializerOptions, uon));
4600         return self();
4601      }
4602
4603      /**
4604       * Sets a default query parameter with parser session options (UON map) for all requests.
4605       *
4606       * <p>
4607       * This is a shortcut for <c>queryDataDefault(stringPart({@link RestSharedConstants#QUERY_juneauParserOptions}, <jv>uon</jv>))</c>.
4608       *
4609       * @param uon
4610       *    Parser session options in UON form.
4611       *    <br>Can be <jk>null</jk> (default is not set by this method).
4612       * @return This object.
4613       */
4614      public SELF parserSessionOptionsQueryDefault(String uon) {
4615         if (uon != null)
4616            queryDataDefault(stringPart(QUERY_juneauParserOptions, uon));
4617         return self();
4618      }
4619
4620      /**
4621       * Convenience for {@link #serializerSessionOptionsQueryDefault(String)} using {@link Uon#of(Object)}.
4622       *
4623       * @param properties
4624       *    Property names and values for serializer session options.
4625       *    <br>Can be <jk>null</jk> (treated as an empty map).
4626       * @return This object.
4627       */
4628      public SELF serializerSessionOptionsQueryDefault(Map<String,?> properties) {
4629         try {
4630            return serializerSessionOptionsQueryDefault(isEmpty(properties) ? null : Uon.of(properties));
4631         } catch (SerializeException e) {
4632            throw rex(e, "Could not serialize serializer session options query default");
4633         }
4634      }
4635
4636      /**
4637       * Convenience for {@link #parserSessionOptionsQueryDefault(String)} using {@link Uon#of(Object)}.
4638       *
4639       * @param properties
4640       *    Property names and values for parser session options.
4641       *    <br>Can be <jk>null</jk> (treated as an empty map).
4642       * @return This object.
4643       */
4644      public SELF parserSessionOptionsQueryDefault(Map<String,?> properties) {
4645         try {
4646            return parserSessionOptionsQueryDefault(isEmpty(properties) ? null : Uon.of(properties));
4647         } catch (SerializeException e) {
4648            throw rex(e, "Could not serialize parser session options query default");
4649         }
4650      }
4651
4652      /**
4653       * <i><l>WriterSerializer</l> configuration property:&emsp;</i>  Quote character.
4654       *
4655       * <p>
4656       * Specifies the character to use for quoting attributes and values.
4657       *
4658       * <h5 class='section'>Notes:</h5><ul>
4659       *    <li class='note'>This setting does not apply to the RDF serializers.
4660       * </ul>
4661       *
4662       * <h5 class='section'>Example:</h5>
4663       * <p class='bjava'>
4664       *    <jc>// Create a REST client with JSON serializer that uses single quotes.</jc>
4665       *    RestClient <jv>client</jv> = RestClient
4666       *       .<jsm>create</jsm>()
4667       *       .json()
4668       *       .quoteChar(<js>'\''</js>)
4669       *       .build();
4670       *
4671       *    <jc>// A bean with a single property</jc>
4672       *    <jk>public class</jk> MyBean {
4673       *       <jk>public</jk> String <jf>foo</jf> = <js>"bar"</js>;
4674       *    }
4675       *
4676       *    <jc>// Request body will contain:  {'foo':'bar'}</jc>
4677       *    <jv>client</jv>
4678       *       .post(<js>"http://localhost:10000/foo"</js>, <jk>new</jk> MyBean())
4679       *       .run();
4680       * </p>
4681       *
4682       * <h5 class='section'>See Also:</h5><ul>
4683       *    <li class='jm'>{@link org.apache.juneau.marshall.serializer.WriterSerializer.Builder#quoteChar(char) WriterSerializer.Builder#quoteChar(char)}
4684       * </ul>
4685       *
4686       * @param value
4687       *    The new value for this property.
4688       *    <br>The default is <js>'"'</js>.
4689       * @return This object.
4690       */
4691      public SELF quoteChar(char value) {
4692         serializers().forEachWS(x -> x.quoteChar(value));
4693         return self();
4694      }
4695
4696      /**
4697       * Assigns {@link RedirectStrategy} instance.
4698       *
4699       * <h5 class='section'>Notes:</h5><ul>
4700       *    <li class='note'>This value can be overridden by the {@link #disableRedirectHandling()} method.
4701       * </ul>
4702       *
4703       * @param redirectStrategy New property value.
4704       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
4705       * @return This object.
4706       * @see HttpClientBuilder#setRedirectStrategy(RedirectStrategy)
4707       */
4708      public SELF redirectStrategy(RedirectStrategy redirectStrategy) {
4709         httpClientBuilder().setRedirectStrategy(redirectStrategy);
4710         return self();
4711      }
4712
4713      /**
4714       * Assigns {@link HttpRequestExecutor} instance.
4715       *
4716       * @param requestExec New property value.
4717       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
4718       * @return This object.
4719       * @see HttpClientBuilder#setRequestExecutor(HttpRequestExecutor)
4720       */
4721      public SELF requestExecutor(HttpRequestExecutor requestExec) {
4722         httpClientBuilder().setRequestExecutor(requestExec);
4723         return self();
4724      }
4725
4726      /**
4727       * Assigns {@link HttpRequestRetryHandler} instance.
4728       *
4729       * <h5 class='section'>Notes:</h5><ul>
4730       *    <li class='note'>This value can be overridden by the {@link #disableAutomaticRetries()} method.
4731       * </ul>
4732       *
4733       * @param retryHandler New property value.
4734       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
4735       * @return This object.
4736       * @see HttpClientBuilder#setRetryHandler(HttpRequestRetryHandler)
4737       */
4738      public SELF retryHandler(HttpRequestRetryHandler retryHandler) {
4739         httpClientBuilder().setRetryHandler(retryHandler);
4740         return self();
4741      }
4742
4743      /**
4744       * <i><l>RestClient</l> configuration property:&emsp;</i>  Root URI.
4745       *
4746       * <p>
4747       * When set, relative URI strings passed in through the various rest call methods (e.g. {@link RestClient#get(Object)}
4748       * will be prefixed with the specified root.
4749       * <br>This root URI is ignored on those methods if you pass in a {@link URL}, {@link URI}, or an absolute URI string.
4750       *
4751       * <h5 class='section'>Example:</h5>
4752       * <p class='bjava'>
4753       *    <jc>// Create a client that uses UON format by default for HTTP parts.</jc>
4754       *    RestClient <jv>client</jv> = RestClient
4755       *       .<jsm>create</jsm>()
4756       *       .rootUrl(<js>"http://localhost:10000/foo"</js>)
4757       *       .build();
4758       *
4759       *    Bar <jv>bar</jv> = <jv>client</jv>
4760       *       .get(<js>"/bar"</js>)  <jc>// Relative to http://localhost:10000/foo</jc>
4761       *       .run()
4762       *       .getContent().as(Bar.<jk>class</jk>);
4763       * </p>
4764       *
4765       * @param value
4766       *    The root URI to prefix to relative URI strings.
4767       *    <br>Trailing slashes are trimmed.
4768       *    <br>Usually a <c>String</c> but you can also pass in <c>URI</c> and <c>URL</c> objects as well.
4769       *    <br>Can be <jk>null</jk> (no root URL will be set).
4770       * @return This object.
4771       */
4772      public SELF rootUrl(Object value) {
4773         var s = s(value);
4774         if (ine(s))
4775            s = s.replaceAll("\\/$", "");
4776         if (isEmpty(s))
4777            rootUrl = null;
4778         else if (s.indexOf("://") == -1)
4779            throw rex("Invalid rootUrl value: '%s'.  Must be a valid absolute URL.", value);
4780         else {
4781            final var url = s;
4782            rootUrl = () -> url;
4783         }
4784         return self();
4785      }
4786
4787      /**
4788       * Sets the root URL using a supplier, allowing the URL to be computed dynamically at request time.
4789       *
4790       * <p>
4791       * The supplier is called on every request, so the URL can change between requests.
4792       * No build-time validation is performed; invalid values will surface as errors when requests are made.
4793       *
4794       * <p>
4795       * Three common patterns are supported:
4796       * <ul>
4797       *    <li>
4798       *       <b>Swappable reference</b> &mdash; Use an {@link AtomicReference AtomicReference}
4799       *       when you need to point the client at a different host at any time:
4800       *       <p class='bjava'>
4801       *          AtomicReference&lt;String&gt; <jv>urlRef</jv> = <jk>new</jk> AtomicReference&lt;&gt;(<js>"https://host1"</js>);
4802       *          RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().rootUrl(<jv>urlRef</jv>::get).build();
4803       *
4804       *          <jc>// Switch to a different host at runtime.</jc>
4805       *          <jv>urlRef</jv>.set(<js>"https://host2"</js>);
4806       *       </p>
4807       *    <li>
4808       *       <b>Refreshable cached value</b> &mdash; Use {@link Memoizer Memoizer}
4809       *       (via {@link Suppliers#memoizer(Supplier) Suppliers.memoizer()})
4810       *       when computing the URL is expensive (e.g. service discovery) and you want it cached until explicitly refreshed:
4811       *       <p class='bjava'>
4812       *          Memoizer&lt;String&gt; <jv>url</jv> = <jsm>memoizer</jsm>(() -&gt; serviceDiscovery.<jsm>findUrl</jsm>(<js>"my-service"</js>));
4813       *          RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().rootUrl(<jv>url</jv>).build();
4814       *
4815       *          <jc>// Force re-evaluation on the next request (e.g. after a failover).</jc>
4816       *          <jv>url</jv>.reset();
4817       *       </p>
4818       *    <li>
4819       *       <b>Purely dynamic</b> &mdash; Use a plain lambda when the URL must be re-evaluated on every request:
4820       *       <p class='bjava'>
4821       *          RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().rootUrl(() -&gt; config.<jsm>getRootUrl</jsm>()).build();
4822       *       </p>
4823       * </ul>
4824       *
4825       * @param value
4826       *    A supplier that returns the root URI to prefix to relative URI strings.
4827       *    <br>Can be <jk>null</jk> (no root URL will be set).
4828       * @return This object.
4829       */
4830      public SELF rootUrl(Supplier<String> value) {
4831         rootUrl = value;
4832         return self();
4833      }
4834
4835      /**
4836       * Assigns {@link HttpRoutePlanner} instance.
4837       *
4838       * @param routePlanner New property value.
4839       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
4840       * @return This object.
4841       * @see HttpClientBuilder#setRoutePlanner(HttpRoutePlanner)
4842       */
4843      public SELF routePlanner(HttpRoutePlanner routePlanner) {
4844         httpClientBuilder().setRoutePlanner(routePlanner);
4845         return self();
4846      }
4847
4848      /**
4849       * Assigns {@link SchemePortResolver} instance.
4850       *
4851       * @param schemePortResolver New property value.
4852       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
4853       * @return This object.
4854       * @see HttpClientBuilder#setSchemePortResolver(SchemePortResolver)
4855       */
4856      public SELF schemePortResolver(SchemePortResolver schemePortResolver) {
4857         httpClientBuilder().setSchemePortResolver(schemePortResolver);
4858         return self();
4859      }
4860
4861      /**
4862       * Serializer.
4863       *
4864       * <p>
4865       * Associates the specified {@link Serializer Serializer} with the HTTP client.
4866       *
4867       * <p>
4868       * The serializer is used to serialize POJOs into the HTTP request body.
4869       *
4870       * <h5 class='section'>Notes:</h5><ul>
4871       *    <li class='note'>When using this method that takes in a class, the serializer can be configured using any of the serializer property setters (e.g. {@link #sortCollections()}) or
4872       *    bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
4873       * </ul>
4874       *
4875       * <h5 class='section'>Example:</h5>
4876       * <p class='bjava'>
4877       *    <jc>// Create a client that uses JSON transport for request bodies.</jc>
4878       *    RestClient <jv>client</jv> = RestClient
4879       *       .<jsm>create</jsm>()
4880       *       .serializer(JsonSerializer.<jk>class</jk>)
4881       *       .sortCollections()  <jc>// Sort any collections being serialized.</jc>
4882       *       .build();
4883       * </p>
4884       *
4885       * @param value
4886       *    The new value for this setting.
4887       *    <br>The default is {@link JsonSerializer}.
4888       * @return This object.
4889       */
4890      public SELF serializer(Class<? extends Serializer> value) {
4891         return serializers(value);
4892      }
4893
4894      /**
4895       * Serializer.
4896       *
4897       * <p>
4898       * Associates the specified {@link Serializer Serializer} with the HTTP client.
4899       *
4900       * <p>
4901       * The serializer is used to serialize POJOs into the HTTP request body.
4902       *
4903       * <h5 class='section'>Notes:</h5><ul>
4904       *    <li class='note'>When using this method that takes in a pre-instantiated serializer, the serializer property setters (e.g. {@link #sortCollections()}) or
4905       *    bean context property setters (e.g. {@link #swaps(Class...)}) defined
4906       *    on this builder class have no effect.
4907       * </ul>
4908       *
4909       * <h5 class='section'>Example:</h5>
4910       * <p class='bjava'>
4911       *    <jc>// Create a client that uses a predefined JSON serializer request bodies.</jc>
4912       *    RestClient <jv>client</jv> = RestClient
4913       *       .<jsm>create</jsm>()
4914       *       .serializer(JsonSerializer.<jsf>DEFAULT_READABLE</jsf>)
4915       *       .build();
4916       * </p>
4917       *
4918       * @param value
4919       *    The new value for this setting.
4920       *    <br>The default is {@link JsonSerializer}.
4921       *    <br>Cannot be <jk>null</jk>.
4922       * @return This object.
4923       */
4924      public SELF serializer(Serializer value) {
4925         return serializers(value);
4926      }
4927
4928      /**
4929       * Returns the serializer group sub-builder.
4930       *
4931       * @return The serializer group sub-builder.
4932       */
4933      public final SerializerSet.Builder serializers() {
4934         if (serializers == null)
4935            serializers = createSerializers();
4936         return serializers;
4937      }
4938
4939      /**
4940       * Serializers.
4941       *
4942       * <p>
4943       * Associates the specified {@link Serializer Serializers} with the HTTP client.
4944       *
4945       * <p>
4946       * The serializer is used to serialize POJOs into the HTTP request body.
4947       *
4948       * <p>
4949       * The serializer that best matches the <c>Content-Type</c> header will be used to serialize the request body.
4950       * <br>If no <c>Content-Type</c> header is specified, the first serializer in the list will be used.
4951       *
4952       * <h5 class='section'>Notes:</h5><ul>
4953       *    <li class='note'>When using this method that takes in classes, the serializers can be configured using any of the serializer property setters (e.g. {@link #sortCollections()}) or
4954       *    bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
4955       * </ul>
4956       *
4957       * <h5 class='section'>Example:</h5>
4958       * <p class='bjava'>
4959       *    <jc>// Create a client that uses JSON and XML transport for request bodies.</jc>
4960       *    RestClient <jv>client</jv> = RestClient
4961       *       .<jsm>create</jsm>()
4962       *       .serializers(JsonSerializer.<jk>class</jk>, XmlSerializer.<jk>class</jk>)
4963       *       .sortCollections()  <jc>// Sort any collections being serialized.</jc>
4964       *       .build();
4965       * </p>
4966       *
4967       * @param value
4968       *    The new value for this setting.
4969       *    <br>The default is {@link JsonSerializer}.
4970       * @return This object.
4971       */
4972      public SELF serializers(Class<? extends Serializer>...value) {
4973         reqnns("value", value);
4974         serializers().add(value);
4975         return self();
4976      }
4977
4978      /**
4979       * Serializers.
4980       *
4981       * <p>
4982       * Associates the specified {@link Serializer Serializers} with the HTTP client.
4983       *
4984       * <p>
4985       * The serializer is used to serialize POJOs into the HTTP request body.
4986       *
4987       * <p>
4988       * The serializer that best matches the <c>Content-Type</c> header will be used to serialize the request body.
4989       * <br>If no <c>Content-Type</c> header is specified, the first serializer in the list will be used.
4990       *
4991       * <h5 class='section'>Notes:</h5><ul>
4992       *    <li class='note'>When using this method that takes in a pre-instantiated serializers, the serializer property setters (e.g. {@link #sortCollections()}) or
4993       *    bean context property setters (e.g. {@link #swaps(Class...)}) defined
4994       *    on this builder class have no effect.
4995       * </ul>
4996       *
4997       * <h5 class='section'>Example:</h5>
4998       * <p class='bjava'>
4999       *    <jc>// Create a client that uses predefined JSON and XML serializers for request bodies.</jc>
5000       *    RestClient <jv>client</jv> = RestClient
5001       *       .<jsm>create</jsm>()
5002       *       .serializers(JsonSerializer.<jsf>DEFAULT_READABLE</jsf>, XmlSerializer.<jsf>DEFAULT_READABLE</jsf>)
5003       *       .build();
5004       * </p>
5005       *
5006       * @param value
5007       *    The new value for this setting.
5008       *    <br>The default is {@link JsonSerializer}.
5009       * @return This object.
5010       */
5011      public SELF serializers(Serializer...value) {
5012         reqnns("value", value);
5013         serializers().add(value);
5014         return self();
5015      }
5016
5017      /**
5018       * Assigns {@link ServiceUnavailableRetryStrategy} instance.
5019       *
5020       * @param serviceUnavailStrategy New property value.
5021       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
5022       * @return This object.
5023       * @see HttpClientBuilder#setServiceUnavailableRetryStrategy(ServiceUnavailableRetryStrategy)
5024       */
5025      public SELF serviceUnavailableRetryStrategy(ServiceUnavailableRetryStrategy serviceUnavailStrategy) {
5026         httpClientBuilder().setServiceUnavailableRetryStrategy(serviceUnavailStrategy);
5027         return self();
5028      }
5029
5030      /**
5031       * Skip empty form data.
5032       *
5033       * <p>
5034       * When enabled, form data consisting of empty strings will be skipped on requests.
5035       * Note that <jk>null</jk> values are already skipped.
5036       *
5037       * <p>
5038       * The {@link Schema#skipIfEmpty()} annotation overrides this setting.
5039       *
5040       * @return This object.
5041       */
5042      public SELF skipEmptyFormData() {
5043         return skipEmptyFormData(true);
5044      }
5045
5046      /**
5047       * Skip empty form data.
5048       *
5049       * <p>
5050       * When enabled, form data consisting of empty strings will be skipped on requests.
5051       * Note that <jk>null</jk> values are already skipped.
5052       *
5053       * <p>
5054       * The {@link Schema#skipIfEmpty()} annotation overrides this setting.
5055       *
5056       * @param value
5057       *    The new value for this setting.
5058       *    <br>The default is <jk>false</jk>.
5059       * @return This object.
5060       */
5061      public SELF skipEmptyFormData(boolean value) {
5062         skipEmptyFormData = value;
5063         return self();
5064      }
5065
5066      /**
5067       * Skip empty header data.
5068       *
5069       * <p>
5070       * When enabled, headers consisting of empty strings will be skipped on requests.
5071       * Note that <jk>null</jk> values are already skipped.
5072       *
5073       * <p>
5074       * The {@link Schema#skipIfEmpty()} annotation overrides this setting.
5075       *
5076       * @return This object.
5077       */
5078      public SELF skipEmptyHeaderData() {
5079         return skipEmptyHeaderData(true);
5080      }
5081
5082      /**
5083       * Skip empty header data.
5084       *
5085       * <p>
5086       * When enabled, headers consisting of empty strings will be skipped on requests.
5087       * Note that <jk>null</jk> values are already skipped.
5088       *
5089       * <p>
5090       * The {@link Schema#skipIfEmpty()} annotation overrides this setting.
5091       *
5092       * @param value
5093       *    The new value for this setting.
5094       *    <br>The default is <jk>false</jk>.
5095       * @return This object.
5096       */
5097      public SELF skipEmptyHeaderData(boolean value) {
5098         skipEmptyHeaderData = value;
5099         return self();
5100      }
5101
5102      /**
5103       * Skip empty query data.
5104       *
5105       * <p>
5106       * When enabled, query parameters consisting of empty strings will be skipped on requests.
5107       * Note that <jk>null</jk> values are already skipped.
5108       *
5109       * <p>
5110       * The {@link Schema#skipIfEmpty()} annotation overrides this setting.
5111       *
5112       * @return This object.
5113       */
5114      public SELF skipEmptyQueryData() {
5115         return skipEmptyQueryData(true);
5116      }
5117
5118      /**
5119       * Skip empty query data.
5120       *
5121       * <p>
5122       * When enabled, query parameters consisting of empty strings will be skipped on requests.
5123       * Note that <jk>null</jk> values are already skipped.
5124       *
5125       * <p>
5126       * The {@link Schema#skipIfEmpty()} annotation overrides this setting.
5127       *
5128       * @param value
5129       *    The new value for this setting.
5130       *    <br>The default is <jk>false</jk>.
5131       * @return This object.
5132       */
5133      public SELF skipEmptyQueryData(boolean value) {
5134         skipEmptyQueryData = value;
5135         return self();
5136      }
5137
5138      /**
5139       * <i><l>Serializer</l> configuration property:&emsp;</i>  Sort arrays and collections alphabetically.
5140       *
5141       * <p>
5142       * When enabled, copies and sorts the contents of arrays and collections before serializing them.
5143       *
5144       * <p>
5145       * Note that this introduces a performance penalty since it requires copying the existing collection.
5146       *
5147       * <h5 class='section'>Example:</h5>
5148       * <p class='bjava'>
5149       *    <jc>// Create a REST client with JSON serializer that sorts arrays and collections before serialization.</jc>
5150       *    RestClient <jv>client</jv> = RestClient
5151       *       .<jsm>create</jsm>()
5152       *       .json()
5153       *       .sortCollections()
5154       *       .build();
5155       *
5156       *    <jc>// An unsorted array</jc>
5157       *    String[] <jv>array</jv> = {<js>"foo"</js>,<js>"bar"</js>,<js>"baz"</js>}
5158       *
5159       *    <jc>// Request body will contain:  ["bar","baz","foo"]</jc>
5160       *    <jv>client</jv>
5161       *       .post(<js>"http://localhost:10000/foo"</js>, <jv>array</jv>)
5162       *       .run();
5163       * </p>
5164       *
5165       * <h5 class='section'>See Also:</h5><ul>
5166       *    <li class='jm'>{@link org.apache.juneau.marshall.serializer.Serializer.Builder#sortCollections() Serializer.Builder#sortCollections()}
5167       * </ul>
5168       *
5169       * @return This object.
5170       */
5171      public SELF sortCollections() {
5172         serializers().forEach(Serializer.Builder::sortCollections);
5173         return self();
5174      }
5175
5176      /**
5177       * <i><l>Serializer</l> configuration property:&emsp;</i>  Sort maps alphabetically.
5178       *
5179       * <p>
5180       * When enabled, copies and sorts the contents of maps by their keys before serializing them.
5181       *
5182       * <p>
5183       * Note that this introduces a performance penalty.
5184       *
5185       * <h5 class='section'>Example:</h5>
5186       * <p class='bjava'>
5187       *    <jc>// Create a REST client with JSON serializer that sorts maps before serialization.</jc>
5188       *    RestClient <jv>client</jv> = RestClient
5189       *       .<jsm>create</jsm>()
5190       *       .json()
5191       *       .sortMaps()
5192       *       .build();
5193       *
5194       *    <jc>// An unsorted map.</jc>
5195       *    AMap <jv>map</jv> = AMap.<jsm>of</jsm>(<js>"foo"</js>,1,<js>"bar"</js>,2,<js>"baz"</js>,3);
5196       *
5197       *    <jc>// Request body will contain:  {"bar":2,"baz":3,"foo":1}</jc>
5198       *    <jv>client</jv>
5199       *       .post(<js>"http://localhost:10000/foo"</js>, <jv>map</jv>)
5200       *       .run();
5201       * </p>
5202       *
5203       * <h5 class='section'>See Also:</h5><ul>
5204       *    <li class='jm'>{@link org.apache.juneau.marshall.serializer.Serializer.Builder#sortMaps() Serializer.Builder#sortMaps()}
5205       * </ul>
5206       *
5207       * @return This object.
5208       */
5209      public SELF sortMaps() {
5210         serializers().forEach(Serializer.Builder::sortMaps);
5211         return self();
5212      }
5213
5214      /**
5215       * <i><l>WriterSerializer</l> configuration property:&emsp;</i>  Quote character.
5216       *
5217       * <p>
5218       * Specifies to use single quotes for quoting attributes and values.
5219       *
5220       * <h5 class='section'>Notes:</h5><ul>
5221       *    <li class='note'>This setting does not apply to the RDF serializers.
5222       * </ul>
5223       *
5224       * <h5 class='section'>Example:</h5>
5225       * <p class='bjava'>
5226       *    <jc>// Create a REST client with JSON serializer that uses single quotes.</jc>
5227       *    RestClient <jv>client</jv> = RestClient
5228       *       .<jsm>create</jsm>()
5229       *       .json()
5230       *       .sq()
5231       *       .build();
5232       *
5233       *    <jc>// A bean with a single property</jc>
5234       *    <jk>public class</jk> MyBean {
5235       *       <jk>public</jk> String <jf>foo</jf> = <js>"bar"</js>;
5236       *    }
5237       *
5238       *    <jc>// Request body will contain:  {'foo':'bar'}</jc>
5239       *    <jv>client</jv>
5240       *       .post(<js>"http://localhost:10000/foo"</js>, <jk>new</jk> MyBean())
5241       *       .run();
5242       * </p>
5243       *
5244       * <h5 class='section'>See Also:</h5><ul>
5245       *    <li class='jm'>{@link org.apache.juneau.marshall.serializer.WriterSerializer.Builder#quoteChar(char) WriterSerializer.Builder#quoteChar(char)}
5246       * </ul>
5247       *
5248       * @return This object.
5249       */
5250      public SELF sq() {
5251         serializers().forEachWS(WriterSerializer.Builder::sq);
5252         return self();
5253      }
5254
5255      /**
5256       * Assigns {@link SSLContext} instance.
5257       *
5258       * <p>
5259       * The context (for example one initialized with a custom trust store) is used for {@code https} connections, with
5260       * the {@link #sslHostnameVerifier(HostnameVerifier) hostname verifier} if one is set, or the default one.
5261       *
5262       * <h5 class='section'>Notes:</h5><ul>
5263       *    <li class='note'>It is applied to the connection manager the default {@link #createConnectionManager()} builds, for
5264       *       both ordinary requests and the internal pool for SSRF-guard-active {@code @Remote} calls.  It has no effect on
5265       *       a connection manager supplied through {@link #connectionManager(HttpClientConnectionManager)} or an overridden
5266       *       {@link #createConnectionManager()}, which carries its own socket factories.
5267       *    <li class='note'>An {@link #sslSocketFactory(LayeredConnectionSocketFactory) SSL socket factory} takes precedence
5268       *       over this value, including one set with
5269       *       {@link HttpClientBuilder#setSSLSocketFactory(LayeredConnectionSocketFactory) setSSLSocketFactory} on a builder
5270       *       passed to {@link #httpClientBuilder(HttpClientBuilder)} after this value was set (as in Apache
5271       *       {@code HttpClientBuilder}).
5272       * </ul>
5273       *
5274       * @param sslContext New property value.
5275       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
5276       * @return This object.
5277       * @see HttpClientBuilder#setSSLContext(SSLContext)
5278       */
5279      public SELF sslContext(SSLContext sslContext) {
5280         this.sslContext = sslContext;
5281         httpClientBuilder().setSSLContext(sslContext);
5282         return self();
5283      }
5284
5285      /**
5286       * Assigns {@link HostnameVerifier} instance.
5287       *
5288       * <h5 class='section'>Notes:</h5><ul>
5289       *    <li class='note'>It is applied to the connection manager the default {@link #createConnectionManager()} builds, for
5290       *       both ordinary requests and the internal pool for SSRF-guard-active {@code @Remote} calls.  It has no effect on
5291       *       a connection manager supplied through {@link #connectionManager(HttpClientConnectionManager)} or an overridden
5292       *       {@link #createConnectionManager()}, which carries its own socket factories.
5293       *    <li class='note'>An {@link #sslSocketFactory(LayeredConnectionSocketFactory) SSL socket factory} takes precedence
5294       *       over this value, including one set with
5295       *       {@link HttpClientBuilder#setSSLSocketFactory(LayeredConnectionSocketFactory) setSSLSocketFactory} on a builder
5296       *       passed to {@link #httpClientBuilder(HttpClientBuilder)} after this value was set (as in Apache
5297       *       {@code HttpClientBuilder}).
5298       * </ul>
5299       *
5300       * @param hostnameVerifier New property value.
5301       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
5302       * @return This object.
5303       * @see HttpClientBuilder#setSSLHostnameVerifier(HostnameVerifier)
5304       */
5305      public SELF sslHostnameVerifier(HostnameVerifier hostnameVerifier) {
5306         this.sslHostnameVerifier = hostnameVerifier;
5307         httpClientBuilder().setSSLHostnameVerifier(hostnameVerifier);
5308         return self();
5309      }
5310
5311      /**
5312       * Assigns {@link LayeredConnectionSocketFactory} instance.
5313       *
5314       * <p>
5315       * The factory is used for {@code https} connections, in place of one built from the
5316       * {@link #sslContext(SSLContext) SSL context} and {@link #sslHostnameVerifier(HostnameVerifier) hostname verifier}.
5317       *
5318       * <h5 class='section'>Notes:</h5><ul>
5319       *    <li class='note'>It is applied to the connection manager the default {@link #createConnectionManager()} builds, for
5320       *       both ordinary requests and the internal pool for SSRF-guard-active {@code @Remote} calls.  It has no effect on
5321       *       a connection manager supplied through {@link #connectionManager(HttpClientConnectionManager)} or an overridden
5322       *       {@link #createConnectionManager()}, which carries its own socket factories.
5323       *    <li class='warn'>For SSRF-guard-active {@code @Remote} calls, the factory is given the address the SSRF pin has
5324       *       already checked (the {@code remoteAddress} of
5325       *       {@link ConnectionSocketFactory#connectSocket(int, Socket, HttpHost, InetSocketAddress, InetSocketAddress, HttpContext) connectSocket}).
5326       *       It must connect to exactly that address: a factory that ignores it and connects by host name (resolving
5327       *       the name again) bypasses the pin.  The same holds for a factory set with
5328       *       {@link HttpClientBuilder#setSSLSocketFactory(LayeredConnectionSocketFactory) setSSLSocketFactory} on a
5329       *       builder passed to {@link #httpClientBuilder(HttpClientBuilder)}.
5330       * </ul>
5331       *
5332       * @param sslSocketFactory New property value.
5333       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
5334       * @return This object.
5335       * @see HttpClientBuilder#setSSLSocketFactory(LayeredConnectionSocketFactory)
5336       */
5337      public SELF sslSocketFactory(LayeredConnectionSocketFactory sslSocketFactory) {
5338         this.sslSocketFactory = sslSocketFactory;
5339         httpClientBuilder().setSSLSocketFactory(sslSocketFactory);
5340         return self();
5341      }
5342
5343      /**
5344       * Assigns {@link AuthenticationStrategy} instance for target host authentication.
5345       *
5346       * @param targetAuthStrategy New property value.
5347       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
5348       * @return This object.
5349       * @see HttpClientBuilder#setTargetAuthenticationStrategy(AuthenticationStrategy)
5350       */
5351      public SELF targetAuthenticationStrategy(AuthenticationStrategy targetAuthStrategy) {
5352         httpClientBuilder().setTargetAuthenticationStrategy(targetAuthStrategy);
5353         return self();
5354      }
5355
5356      /**
5357       * <i><l>Serializer</l> configuration property:&emsp;</i>  Trim empty lists and arrays.
5358       *
5359       * <p>
5360       * When enabled, empty lists and arrays will not be serialized.
5361       *
5362       * <p>
5363       * Note that enabling this setting has the following effects on parsing:
5364       * <ul class='spaced-list'>
5365       *    <li>
5366       *       Map entries with empty list values will be lost.
5367       *    <li>
5368       *       Bean properties with empty list values will not be set.
5369       * </ul>
5370       *
5371       * <h5 class='section'>Example:</h5>
5372       * <p class='bjava'>
5373       *    <jc>// Create a serializer that skips empty arrays and collections.</jc>
5374       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
5375       *       .<jsm>create</jsm>()
5376       *       .trimEmptyCollections()
5377       *       .build();
5378       *
5379       *    <jc>// A bean with a field with an empty array.</jc>
5380       *    <jk>public class</jk> MyBean {
5381       *       <jk>public</jk> String[] <jf>foo</jf> = {};
5382       *    }
5383       *
5384       *    <jc>// Request body will contain:  {}</jc>
5385       *    <jv>client</jv>
5386       *       .post(<js>"http://localhost:10000/foo"</js>, <jk>new</jk> MyBean())
5387       *       .run();
5388       * </p>
5389       *
5390       * <h5 class='section'>See Also:</h5><ul>
5391       *    <li class='jm'>{@link org.apache.juneau.marshall.serializer.Serializer.Builder#trimEmptyCollections() Serializer.Builder#trimEmptyCollections()}
5392       * </ul>
5393       *
5394       * @return This object.
5395       */
5396      public SELF trimEmptyCollections() {
5397         serializers().forEach(Serializer.Builder::trimEmptyCollections);
5398         return self();
5399      }
5400
5401      /**
5402       * <i><l>Serializer</l> configuration property:&emsp;</i>  Trim empty maps.
5403       *
5404       * <p>
5405       * When enabled, empty map values will not be serialized to the output.
5406       *
5407       * <p>
5408       * Note that enabling this setting has the following effects on parsing:
5409       * <ul class='spaced-list'>
5410       *    <li>
5411       *       Bean properties with empty map values will not be set.
5412       * </ul>
5413       *
5414       * <h5 class='section'>Example:</h5>
5415       * <p class='bjava'>
5416       *    <jc>// Create a REST client with JSON serializer that skips empty maps.</jc>
5417       *    RestClient <jv>client</jv> = RestClient
5418       *       .<jsm>create</jsm>()
5419       *       .json()
5420       *       .trimEmptyMaps()
5421       *       .build();
5422       *
5423       *    <jc>// A bean with a field with an empty map.</jc>
5424       *    <jk>public class</jk> MyBean {
5425       *       <jk>public</jk> AMap <jf>foo</jf> = AMap.<jsm>of</jsm>();
5426       *    }
5427       *
5428       *    <jc>// Request body will contain:  {}</jc>
5429       *    <jv>client</jv>
5430       *       .post(<js>"http://localhost:10000/foo"</js>, <jk>new</jk> MyBean())
5431       *       .run();
5432       * </p>
5433       *
5434       * <h5 class='section'>See Also:</h5><ul>
5435       *    <li class='jm'>{@link org.apache.juneau.marshall.serializer.Serializer.Builder#trimEmptyMaps() Serializer.Builder#trimEmptyMaps()}
5436       * </ul>
5437       *
5438       * @return This object.
5439       */
5440      public SELF trimEmptyMaps() {
5441         serializers().forEach(Serializer.Builder::trimEmptyMaps);
5442         return self();
5443      }
5444
5445      /**
5446       * <i><l>Parser</l> configuration property:&emsp;</i>  Trim parsed strings.
5447       *
5448       * <p>
5449       * When enabled, string values will be trimmed of whitespace using {@link String#trim()} before being added to
5450       * the POJO.
5451       *
5452       * <h5 class='section'>Example:</h5>
5453       * <p class='bjava'>
5454       *    <jc>// Create a REST client with JSON parser with trim-strings enabled.</jc>
5455       *    RestClient <jv>client</jv> = RestClient
5456       *       .<jsm>create</jsm>()
5457       *       .json()
5458       *       .trimStringsOnRead()
5459       *       .build();
5460       *
5461       *    <jc>// Try to parse JSON containing {" foo ":" bar "}.</jc>
5462       *    Map&lt;String,String&gt; <jv>map</jv> = <jv>client</jv>
5463       *       .get(<js>"/pathToJson"</js>)
5464       *       .run()
5465       *       .getContent().as(HashMap.<jk>class</jk>, String.<jk>class</jk>, String.<jk>class</jk>);
5466       *
5467       *    <jc>// Make sure strings are trimmed.</jc>
5468       *    <jsm>assertEquals</jsm>(<js>"bar"</js>, <jv>map</jv>.get(<js>"foo"</js>));
5469       * </p>
5470       *
5471       * <h5 class='section'>See Also:</h5><ul>
5472       *    <li class='jm'>{@link org.apache.juneau.marshall.parser.Parser.Builder#trimStrings() Parser.Builder#trimStrings()}
5473       * </ul>
5474       *
5475       * @return This object.
5476       */
5477      public SELF trimStringsOnRead() {
5478         parsers().forEach(Parser.Builder::trimStrings);
5479         return self();
5480      }
5481
5482      /**
5483       * <i><l>Serializer</l> configuration property:&emsp;</i>  Trim strings.
5484       *
5485       * <p>
5486       * When enabled, string values will be trimmed of whitespace using {@link String#trim()} before being serialized.
5487       *
5488       * <h5 class='section'>Example:</h5>
5489       * <p class='bjava'>
5490       *    <jc>// Create a REST client with JSON serializer that trims strings before serialization.</jc>
5491       *    RestClient <jv>client</jv> = RestClient
5492       *       .<jsm>create</jsm>()
5493       *       .json()
5494       *       .trimStrings()
5495       *       .build();
5496       *
5497       * <jc>// A map with space-padded keys/values</jc>
5498       *    AMap <jv>map</jv> = AMap.<jsm>of</jsm>(<js>" foo "</js>, <js>" bar "</js>);
5499       *
5500       *    <jc>// Request body will contain:  {"foo":"bar"}</jc>
5501       *    <jv>client</jv>
5502       *       .post(<js>"http://localhost:10000/foo"</js>, <jv>map</jv>)
5503       *       .run();
5504       * </p>
5505       *
5506       * <h5 class='section'>See Also:</h5><ul>
5507       *    <li class='jm'>{@link org.apache.juneau.marshall.serializer.Serializer.Builder#trimStrings() Serializer.Builder#trimStrings()}
5508       * </ul>
5509       *
5510       * @return This object.
5511       */
5512      public SELF trimStringsOnWrite() {
5513         serializers().forEach(Serializer.Builder::trimStrings);
5514         return self();
5515      }
5516
5517      /**
5518       * Convenience method for specifying all available transmission types.
5519       *
5520       * <p>
5521       *    All basic Juneau serializers will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
5522       *    <ul>
5523       *       <li>The serializers can be configured using any of the serializer property setters (e.g. {@link #sortCollections()}) or
5524       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
5525       *    </ul>
5526       * <p>
5527       *    All basic Juneau parsers will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
5528       *    <ul>
5529       *       <li>The parsers can be configured using any of the parser property setters (e.g. {@link #ignoreUnknownBeanProperties()}) or
5530       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
5531       *    </ul>
5532       * <p>
5533       *    <c>Accept</c> request header must be set via {@link #headers()}, or per-request
5534       *       via {@link RestRequest#header(Header)} in order for the correct parser to be selected.
5535       * <p>
5536       *    <c>Content-Type</c> request header must be set via {@link #headers()},
5537       *       or per-request via {@link RestRequest#header(Header)} in order for the correct serializer to be selected.
5538       * <p>
5539       *    Similar to calling <c>json().json5().html().xml().uon().urlEnc().openApi().msgPack().plainText()</c>.
5540       *
5541       * <h5 class='section'>Example:</h5>
5542       * <p class='bjava'>
5543       *    <jc>// Construct a client that uses universal marshalling.</jc>
5544       *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().universal().build();
5545       * </p>
5546       *
5547       * @return This object.
5548       */
5549      public SELF universal() {
5550         // @formatter:off
5551         return
5552            serializers(
5553               JsonSerializer.class,
5554               JcsSerializer.class,
5555               Json5Serializer.class,
5556               Json5lSerializer.class,
5557               JsonlSerializer.class,
5558               HtmlSerializer.class,
5559               XmlSerializer.class,
5560               UonSerializer.class,
5561               UrlEncodingSerializer.class,
5562               OpenApiSerializer.class,
5563               BsonSerializer.class,
5564               CborSerializer.class,
5565               MsgPackSerializer.class,
5566               ParquetSerializer.class,
5567               PlainTextSerializer.class,
5568               TomlSerializer.class,
5569               HjsonSerializer.class,
5570               HoconSerializer.class,
5571               IniSerializer.class,
5572               PrototextSerializer.class,
5573               MarkdownSerializer.class
5574            )
5575            .parsers(
5576               JsonParser.class,
5577               Json5Parser.class,
5578               Json5lParser.class,
5579               JsonlParser.class,
5580               XmlParser.class,
5581               HtmlParser.class,
5582               UonParser.class,
5583               UrlEncodingParser.class,
5584               OpenApiParser.class,
5585               BsonParser.class,
5586               CborParser.class,
5587               MsgPackParser.class,
5588               ParquetParser.class,
5589               PlainTextParser.class,
5590               TomlParser.class,
5591               HjsonParser.class,
5592               HoconParser.class,
5593               IniParser.class,
5594               PrototextParser.class,
5595               MarkdownParser.class
5596            );
5597         // @formatter:on
5598      }
5599
5600      /**
5601       * Convenience method for specifying UON as the marshalling transmission media type.
5602       *
5603       * <p>
5604       * UON is Url-Encoding Object notation that is equivalent to JSON but suitable for transmission as URL-encoded
5605       * query and form post values.
5606       *
5607       * <p>
5608       *    {@link UonSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
5609       *    <ul>
5610       *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link #sortCollections()}) or
5611       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
5612       *    </ul>
5613       * <p>
5614       *    {@link UonParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
5615       *    <ul>
5616       *       <li>The parser can be configured using any of the parser property setters (e.g. {@link #ignoreUnknownBeanProperties()}) or
5617       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
5618       *    </ul>
5619       * <p>
5620       *    <c>Accept</c> request header will be set to <js>"text/uon"</js> unless overridden
5621       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
5622       * <p>
5623       *    <c>Content-Type</c> request header will be set to <js>"text/uon"</js> unless overridden
5624       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
5625       * <p>
5626       *    Can be combined with other marshaller setters such as {@link #json()} to provide support for multiple languages.
5627       *    <ul>
5628       *       <li>When multiple languages are supported, the <c>Accept</c> and <c>Content-Type</c> headers control which marshallers are used, or uses the
5629       *       last-enabled language if the headers are not set.
5630       *    </ul>
5631       * <p>
5632       *    Identical to calling <c>serializer(UonSerializer.<jk>class</jk>).parser(UonParser.<jk>class</jk>)</c>.
5633       *
5634       * <h5 class='section'>Example:</h5>
5635       * <p class='bjava'>
5636       *    <jc>// Construct a client that uses UON marshalling.</jc>
5637       *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().uon().build();
5638       * </p>
5639       *
5640       * @return This object.
5641       */
5642      public SELF uon() {
5643         return serializer(UonSerializer.class).parser(UonParser.class);
5644      }
5645
5646      /**
5647       * <i><l>Serializer</l> configuration property:&emsp;</i>  URI context bean.
5648       *
5649       * <p>
5650       * Bean used for resolution of URIs to absolute or root-relative form.
5651       *
5652       * <h5 class='section'>Example:</h5>
5653       * <p class='bjava'>
5654       *    <jc>// Our URI contextual information.</jc>
5655       *    String <jv>authority</jv> = <js>"http://localhost:10000"</js>;
5656       *    String <jv>contextRoot</jv> = <js>"/myContext"</js>;
5657       *    String <jv>servletPath</jv> = <js>"/myServlet"</js>;
5658       *    String <jv>pathInfo</jv> = <js>"/foo"</js>;
5659       *
5660       *    <jc>// Create a UriContext object.</jc>
5661       *    UriContext <jv>uriContext</jv> = <jk>new</jk> UriContext(<jv>authority</jv>, <jv>contextRoot</jv>, <jv>servletPath</jv>, <jv>pathInfo</jv>);
5662       *
5663       *    <jc>// Create a REST client with JSON serializer and associate our context.</jc>
5664       *    RestClient <jv>client</jv> = RestClient
5665       *       .<jsm>create</jsm>()
5666       *       .json()
5667       *       .uriContext(<jv>uriContext</jv>)
5668       *       .uriRelativity(<jsf>RESOURCE</jsf>)  <jc>// Assume relative paths are relative to servlet.</jc>
5669       *       .uriResolution(<jsf>ABSOLUTE</jsf>)  <jc>// Serialize URIs as absolute paths.</jc>
5670       *       .build();
5671       *
5672       *    <jc>// A relative URI</jc>
5673       *    URI <jv>uri</jv> = <jk>new</jk> URI(<js>"bar"</js>);
5674       *
5675       *    <jc>// Request body will contain:  "http://localhost:10000/myContext/myServlet/foo/bar"</jc>
5676       *    <jv>client</jv>
5677       *       .post(<js>"http://localhost:10000/foo"</js>, <jv>uri</jv>)
5678       *       .run();
5679       * </p>
5680       *
5681       * <h5 class='section'>See Also:</h5><ul>
5682       *    <li class='jm'>{@link org.apache.juneau.marshall.serializer.Serializer.Builder#uriContext(UriContext) Serializer.Builder#uriContext(UriContext)}
5683       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/MarshallingUris">URIs</a>
5684       * </ul>
5685       *
5686       * @param value The new value for this property.
5687       *    <br>Cannot be <jk>null</jk>.
5688       * @return This object.
5689       */
5690      public SELF uriContext(UriContext value) {
5691         serializers().forEach(x -> x.uriContext(reqnn("value", value)));
5692         return self();
5693      }
5694
5695      /**
5696       * <i><l>Serializer</l> configuration property:&emsp;</i>  URI relativity.
5697       *
5698       * <p>
5699       * Defines what relative URIs are relative to when serializing any of the following:
5700       * <ul>
5701       *    <li>{@link URI}
5702       *    <li>{@link URL}
5703       *    <li>Properties and classes annotated with {@link Uri @Uri}
5704       * </ul>
5705       *
5706       * <p>
5707       * See {@link #uriContext(UriContext)} for examples.
5708       *
5709       * <ul class='values javatree'>
5710       *    <li class='jf'>{@link UriRelativity#RESOURCE}
5711       *       - Relative URIs should be considered relative to the servlet URI.
5712       *    <li class='jf'>{@link UriRelativity#PATH_INFO}
5713       *       - Relative URIs should be considered relative to the request URI.
5714       * </ul>
5715       *
5716       * <h5 class='section'>See Also:</h5><ul>
5717       *    <li class='jm'>{@link org.apache.juneau.marshall.serializer.Serializer.Builder#uriRelativity(UriRelativity) Serializer.Builder#uriRelativity(UriRelativity)}
5718       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/MarshallingUris">URIs</a>
5719       * </ul>
5720       *
5721       * @param value
5722       *    The new value for this property.
5723       *    <br>The default is {@link UriRelativity#RESOURCE}
5724       *    <br>Cannot be <jk>null</jk>.
5725       * @return This object.
5726       */
5727      public SELF uriRelativity(UriRelativity value) {
5728         serializers().forEach(x -> x.uriRelativity(reqnn("value", value)));
5729         return self();
5730      }
5731
5732      /**
5733       * <i><l>Serializer</l> configuration property:&emsp;</i>  URI resolution.
5734       *
5735       * <p>
5736       * Defines the resolution level for URIs when serializing any of the following:
5737       * <ul>
5738       *    <li>{@link URI}
5739       *    <li>{@link URL}
5740       *    <li>Properties and classes annotated with {@link Uri @Uri}
5741       * </ul>
5742       *
5743       * <p>
5744       * See {@link #uriContext(UriContext)} for examples.
5745       *
5746       * <ul class='values'>
5747       *    <li class='jf'>{@link UriResolution#ABSOLUTE}
5748       *       - Resolve to an absolute URI (e.g. <js>"http://host:port/context-root/servlet-path/path-info"</js>).
5749       *    <li class='jf'>{@link UriResolution#ROOT_RELATIVE}
5750       *       - Resolve to a root-relative URI (e.g. <js>"/context-root/servlet-path/path-info"</js>).
5751       *    <li class='jf'>{@link UriResolution#NONE}
5752       *       - Don't do any URI resolution.
5753       * </ul>
5754       *
5755       * <h5 class='section'>See Also:</h5><ul>
5756       *    <li class='jm'>{@link org.apache.juneau.marshall.serializer.Serializer.Builder#uriResolution(UriResolution) Serializer.Builder#uriResolution(UriResolution)}
5757       *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/MarshallingUris">URIs</a>
5758       * </ul>
5759       *
5760       * @param value
5761       *    The new value for this property.
5762       *    <br>The default is {@link UriResolution#NONE}
5763       *    <br>Cannot be <jk>null</jk>.
5764       * @return This object.
5765       */
5766      public SELF uriResolution(UriResolution value) {
5767         serializers().forEach(x -> x.uriResolution(reqnn("value", value)));
5768         return self();
5769      }
5770
5771      /**
5772       * Convenience method for specifying URL-Encoding as the marshalling transmission media type.
5773       *
5774       * <p>
5775       *    {@link UrlEncodingSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
5776       *    <ul>
5777       *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link #sortCollections()}) or
5778       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
5779       *       <li>This serializer is NOT used when using the {@link RestRequest#formData(String, Object)} (and related) methods for constructing
5780       *          the request body.  Instead, the part serializer specified via {@link #partSerializer(Class)} is used.
5781       *    </ul>
5782       * <p>
5783       *    {@link UrlEncodingParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
5784       *    <ul>
5785       *       <li>The parser can be configured using any of the parser property setters (e.g. {@link #ignoreUnknownBeanProperties()}) or
5786       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
5787       *    </ul>
5788       * <p>
5789       *    <c>Accept</c> request header will be set to <js>"application/x-www-form-urlencoded"</js> unless overridden
5790       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
5791       * <p>
5792       *    <c>Content-Type</c> request header will be set to <js>"application/x-www-form-urlencoded"</js> unless overridden
5793       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
5794       * <p>
5795       *    Can be combined with other marshaller setters such as {@link #json()} to provide support for multiple languages.
5796       *    <ul>
5797       *       <li>When multiple languages are supported, the <c>Accept</c> and <c>Content-Type</c> headers control which marshallers are used, or uses the
5798       *       last-enabled language if the headers are not set.
5799       *    </ul>
5800       * <p>
5801       *    Identical to calling <c>serializer(UrlEncodingSerializer.<jk>class</jk>).parser(UrlEncodingParser.<jk>class</jk>)</c>.
5802       *
5803       * <h5 class='section'>Example:</h5>
5804       * <p class='bjava'>
5805       *    <jc>// Construct a client that uses URL-Encoded marshalling.</jc>
5806       *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().urlEnc().build();
5807       * </p>
5808       *
5809       * @return This object.
5810       */
5811      public SELF urlEnc() {
5812         return serializer(UrlEncodingSerializer.class).parser(UrlEncodingParser.class);
5813      }
5814
5815      /**
5816       * Returns the URL-encoding serializer sub-builder.
5817       *
5818       * @return The URL-encoding serializer sub-builder.
5819       */
5820      public final UrlEncodingSerializer.Builder urlEncodingSerializer() {
5821         if (urlEncodingSerializer == null)
5822            urlEncodingSerializer = createUrlEncodingSerializer();
5823         return urlEncodingSerializer;
5824      }
5825
5826
5827      /**
5828       * Assigns {@link UserTokenHandler} instance.
5829       *
5830       * <h5 class='section'>Notes:</h5><ul>
5831       *    <li class='note'>This value can be overridden by the {@link #disableConnectionState()} method.
5832       * </ul>
5833       *
5834       * @param userTokenHandler New property value.
5835       *    <br>Can be <jk>null</jk> (value will not be set, default behavior will be used).
5836       * @return This object.
5837       * @see HttpClientBuilder#setUserTokenHandler(UserTokenHandler)
5838       */
5839      public SELF userTokenHandler(UserTokenHandler userTokenHandler) {
5840         httpClientBuilder().setUserTokenHandler(userTokenHandler);
5841         return self();
5842      }
5843
5844      /**
5845       * Use system properties when creating and configuring default implementations.
5846       *
5847       * <h5 class='section'>Notes:</h5><ul>
5848       *    <li class='note'>The system properties Apache {@link HttpClientBuilder} reads for its own connection manager
5849       *       apply to both pools of the connection manager the default {@link #createConnectionManager()} builds, as
5850       *       Apache applies them: with no {@link #sslContext(SSLContext) sslContext} or
5851       *       {@link #sslSocketFactory(LayeredConnectionSocketFactory) sslSocketFactory}, {@code https} uses the JVM's
5852       *       default SSL socket factory (the {@code javax.net.ssl.*} trust and key stores); {@code https.protocols} and
5853       *       {@code https.cipherSuites} restrict the TLS versions and cipher suites (unless an {@code sslSocketFactory}
5854       *       is set); and unless {@code http.keepAlive} is {@code false}, {@code http.maxConnections} (default 5) limits
5855       *       the connections per route, and twice that in total, which makes the connection manager a pooling one.
5856       *       {@link #maxConnTotal(int)} and {@link #maxConnPerRoute(int)} win over that limit.
5857       *    <li class='note'>The proxy system properties apply too (see {@link #proxy(HttpHost)}).
5858       * </ul>
5859       *
5860       * @return This object.
5861       * @see HttpClientBuilder#useSystemProperties()
5862       */
5863      public SELF useSystemProperties() {
5864         this.systemProperties = true;
5865         httpClientBuilder().useSystemProperties();
5866         return self();
5867      }
5868
5869      /**
5870       * <i><l>WriterSerializer</l> configuration property:&emsp;</i>  Use whitespace.
5871       *
5872       * <p>
5873       * When enabled, whitespace is added to the output to improve readability.
5874       *
5875       * <h5 class='section'>Example:</h5>
5876       * <p class='bjava'>
5877       *    <jc>// Create a REST client with JSON serializer with whitespace enabled.</jc>
5878       *    RestClient <jv>client</jv> = RestClient
5879       *       .<jsm>create</jsm>()
5880       *       .json()
5881       *       .useWhitespace()
5882       *       .build();
5883       *
5884       *    <jc>// A bean with a single property</jc>
5885       *    <jk>public class</jk> MyBean {
5886       *       <jk>public</jk> String <jf>foo</jf> = <js>"bar"</js>;
5887       *    }
5888       *
5889       *    <jc>// Request body will contain:  {\n\t"foo": "bar"\n\}\n</jc>
5890       *    <jv>client</jv>
5891       *       .post(<js>"http://localhost:10000/foo"</js>, <jk>new</jk> MyBean())
5892       *       .run();
5893       * </p>
5894       *
5895       * <h5 class='section'>See Also:</h5><ul>
5896       *    <li class='jm'>{@link org.apache.juneau.marshall.serializer.WriterSerializer.Builder#useWhitespace() WriterSerializer.Builder#useWhitespace()}
5897       * </ul>
5898       * @return This object.
5899       */
5900      public SELF useWhitespace() {
5901         serializers().forEachWS(WriterSerializer.Builder::useWhitespace);
5902         return self();
5903      }
5904
5905      /**
5906       * <i><l>WriterSerializer</l> configuration property:&emsp;</i>  Use whitespace.
5907       *
5908       * <p>
5909       * When enabled, whitespace is added to the output to improve readability.
5910       *
5911       * <h5 class='section'>Example:</h5>
5912       * <p class='bjava'>
5913       *    <jc>// Create a REST client with JSON serializer with whitespace enabled.</jc>
5914       *    RestClient <jv>client</jv> = RestClient
5915       *       .<jsm>create</jsm>()
5916       *       .json()
5917       *       .ws()
5918       *       .build();
5919       *
5920       *    <jc>// A bean with a single property</jc>
5921       *    <jk>public class</jk> MyBean {
5922       *       <jk>public</jk> String <jf>foo</jf> = <js>"bar"</js>;
5923       *    }
5924       *
5925       *    <jc>// Request body will contain:  {\n\t"foo": "bar"\n\}\n</jc>
5926       *    <jv>client</jv>
5927       *       .post(<js>"http://localhost:10000/foo"</js>, <jk>new</jk> MyBean())
5928       *       .run();
5929       * </p>
5930       *
5931       * <h5 class='section'>See Also:</h5><ul>
5932       *    <li class='jm'>{@link org.apache.juneau.marshall.serializer.WriterSerializer.Builder#useWhitespace() WriterSerializer.Builder#useWhitespace()}
5933       * </ul>
5934       *
5935       * @return This object.
5936       */
5937      public SELF ws() {
5938         serializers().forEachWS(WriterSerializer.Builder::ws);
5939         return self();
5940      }
5941
5942      /**
5943       * Convenience method for specifying XML as the marshalling transmission media type.
5944       *
5945       * <p>
5946       * {@link XmlSerializer} will be used to serialize POJOs to request bodies unless overridden per request via {@link RestRequest#serializer(Serializer)}.
5947       *    <ul>
5948       *       <li>The serializer can be configured using any of the serializer property setters (e.g. {@link #sortCollections()}) or
5949       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
5950       *    </ul>
5951       * <p>
5952       *    {@link XmlParser} will be used to parse POJOs from response bodies unless overridden per request via {@link RestRequest#parser(Parser)}.
5953       *    <ul>
5954       *       <li>The parser can be configured using any of the parser property setters (e.g. {@link #ignoreUnknownBeanProperties()}) or
5955       *          bean context property setters (e.g. {@link #swaps(Class...)}) defined on this builder class.
5956       *    </ul>
5957       * <p>
5958       *    <c>Accept</c> request header will be set to <js>"text/xml"</js> unless overridden
5959       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
5960       * <p>
5961       *    <c>Content-Type</c> request header will be set to <js>"text/xml"</js> unless overridden
5962       *       via {@link #headers()}, or per-request via {@link RestRequest#header(Header)}.
5963       * <p>
5964       *    Can be combined with other marshaller setters such as {@link #json()} to provide support for multiple languages.
5965       *    <ul>
5966       *       <li>When multiple languages are supported, the <c>Accept</c> and <c>Content-Type</c> headers control which marshallers are used, or uses the
5967       *       last-enabled language if the headers are not set.
5968       *    </ul>
5969       * <p>
5970       *    Identical to calling <c>serializer(XmlSerializer.<jk>class</jk>).parser(XmlParser.<jk>class</jk>)</c>.
5971       *
5972       * <h5 class='section'>Example:</h5>
5973       * <p class='bjava'>
5974       *    <jc>// Construct a client that uses XML marshalling.</jc>
5975       *    RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().xml().build();
5976       * </p>
5977       *
5978       * @return This object.
5979       */
5980      public SELF xml() {
5981         return serializer(XmlSerializer.class).parser(XmlParser.class);
5982      }
5983
5984      /**
5985       * Creates the creator for the rest call handler.
5986       *
5987       * <p>
5988       * Subclasses can override this method to provide their own implementation.
5989       *
5990       * <p>
5991       * The default behavior creates a bean instantiator initialized to return a {@link BasicRestCallHandler}.
5992       *
5993       * @return The creator for the rest call handler.
5994       * @see #callHandler()
5995       */
5996      protected BeanInstantiator.Builder<RestCallHandler> createCallHandler() {
5997         return BeanInstantiator.of(RestCallHandler.class, beanStore).type(BasicRestCallHandler.class);
5998      }
5999
6000      /**
6001       * Creates the {@link HttpClientConnectionManager} returned by {@link #createConnectionManager()}.
6002       *
6003       * <p>
6004       * Subclasses can override this method to provide their own connection manager.
6005       *
6006       * <p>
6007       * The default implementation returns a new {@link PoolingHttpClientConnectionManager} if {@link #pooled()},
6008       * {@link #maxConnTotal(int)}, {@link #maxConnPerRoute(int)} or a positive
6009       * {@link #connectionTimeToLive(long, TimeUnit) connectionTimeToLive} was set, or the {@code http.maxConnections}
6010       * limit of {@link #useSystemProperties()} applies (unless {@code http.keepAlive} is {@code false}), or a new
6011       * {@link BasicHttpClientConnectionManager} if not.  It applies the {@link #sslContext(SSLContext) sslContext},
6012       * {@link #sslSocketFactory(LayeredConnectionSocketFactory) sslSocketFactory},
6013       * {@link #sslHostnameVerifier(HostnameVerifier) sslHostnameVerifier}, {@code maxConnTotal} and {@code maxConnPerRoute}
6014       * settings, which Apache {@link HttpClientBuilder} ignores once a connection manager is set.  It also applies, to
6015       * both pools, the other settings Apache {@code HttpClientBuilder} applies only to a connection manager it builds
6016       * itself, whether made through this builder or directly on the {@link #httpClientBuilder() HttpClientBuilder}:
6017       * {@link #publicSuffixMatcher(PublicSuffixMatcher) publicSuffixMatcher} (for the default hostname verifier),
6018       * {@link #defaultSocketConfig(SocketConfig) defaultSocketConfig},
6019       * {@link #defaultConnectionConfig(ConnectionConfig) defaultConnectionConfig},
6020       * {@link #connectionTimeToLive(long, TimeUnit) connectionTimeToLive} (which, like {@code maxConnTotal} and
6021       * {@code maxConnPerRoute}, makes it a {@code PoolingHttpClientConnectionManager}) and the TLS and
6022       * {@code http.maxConnections} system properties of {@link #useSystemProperties()}.  A
6023       * {@link HttpClientBuilder#setDnsResolver(DnsResolver) DNS resolver} set on the {@code HttpClientBuilder} is used
6024       * for ordinary requests only: SSRF-guard-active {@code @Remote} calls always resolve through the SSRF pin.
6025       * Each of these settings made through this builder also survives {@link #httpClientBuilder(HttpClientBuilder)}
6026       * replacing the {@code HttpClientBuilder}, and always wins over the same setting on the {@code HttpClientBuilder},
6027       * whichever was set last (unlike Apache's own last-write-wins).  An SSL socket factory wins over any SSL context,
6028       * wherever each was set.  The {@code HttpClientBuilder}'s settings are read from its fields (it has no getters);
6029       * if they cannot be read, this method throws an {@link IllegalStateException} rather than ignore them.
6030       *
6031       * <p>
6032       * Each {@link #build()} calls this method again, so a builder reused after {@code build()} gives every client its
6033       * own connection manager (closing one client does not shut down another's).  A connection manager supplied through
6034       * {@link #connectionManager(HttpClientConnectionManager)} is used as is by every client built.
6035       *
6036       * <p>
6037       * SSRF-guard-active {@code @Remote} calls do not use this connection manager: the default
6038       * {@link #createHttpClient()} pairs it with a second, dedicated one whose connections are all opened through the
6039       * SSRF pin, so that a guarded call never reuses a connection an ordinary request opened.  It can only do that
6040       * for the instance this default implementation returns.  If an override returns any other connection manager,
6041       * the client refuses every SSRF-guard-active {@code @Remote} call (one without the
6042       * {@link #allowPrivateUrls(boolean) allowPrivateUrls} opt-in).
6043       *
6044       * <p>
6045       * The dedicated connection manager copies this one's settings before each guarded call, but it is a separate pool:
6046       * limits such as {@link PoolingHttpClientConnectionManager#setMaxTotal(int) maxTotal} apply to each pool on its
6047       * own, so a client that mixes ordinary and guarded calls can hold up to twice as many open connections.
6048       *
6049       * <h5 class='section'>Example:</h5>
6050       * <p class='bjava'>
6051       *    <jc>// A Builder that provides it's own customized HttpClientConnectionManager.</jc>
6052       *    <jk>public class</jk> MyBuilder <jk>extends</jk> Builder {
6053       *       <ja>@Override</ja>
6054       *       <jk>protected</jk> HttpClientConnectionManager createConnectionManager() {
6055       *          <jk>return new</jk> PoolingHttpClientConnectionManager();
6056       *       }
6057       *    }
6058       *
6059       *    <jc>// Instantiate.</jc>
6060       *    RestClient <jv>client</jv> = <jk>new</jk> MyBuilder().build();
6061       * </p>
6062       *
6063       * @return The connection manager to use.
6064       */
6065      protected HttpClientConnectionManager createConnectionManager() {
6066         var s = HttpClientBuilderSettings.of(httpClientBuilder());
6067         defaultRegistry = socketFactoryRegistry(s);
6068         defaultPoolSettings = poolSettings(s);
6069         defaultConnectionManager = newConnectionManager(defaultRegistry, or(s.dnsResolver(), SystemDefaultDnsResolver.INSTANCE), defaultPoolSettings);
6070         return defaultConnectionManager;
6071      }
6072
6073      // The socket factories for the TLS settings, chosen as Apache HttpClientBuilder chooses them when it builds its own
6074      // connection manager: the SSL socket factory, else one on the SSL context (else the JVM's default socket factory
6075      // under useSystemProperties(), else a default context) with the hostname verifier (else the default verifier on
6076      // the public suffix matcher) and, under useSystemProperties(), the https.protocols and https.cipherSuites.
6077      // A setting made through this builder always wins over the same setting read from the HttpClientBuilder, whichever
6078      // was set last.  The two differ when httpClientBuilder(...) replaced the builder after the setting was made, or when
6079      // the setting was later made again directly on httpClientBuilder().  As in Apache, a socket factory wins over any
6080      // SSL context, wherever each was set.
6081      private Registry<ConnectionSocketFactory> socketFactoryRegistry(HttpClientBuilderSettings s) {
6082         var https = or(sslSocketFactory, s.sslSocketFactory());
6083         if (https == null) {
6084            var sysProps = systemProperties || s.systemProperties();
6085            var protocols = sysProps ? splitSystemProperty("https.protocols") : null;
6086            var cipherSuites = sysProps ? splitSystemProperty("https.cipherSuites") : null;
6087            var verifier = or(sslHostnameVerifier, s.hostnameVerifier());
6088            if (verifier == null)
6089               verifier = new DefaultHostnameVerifier(or(publicSuffixMatcher, s.publicSuffixMatcher(), PublicSuffixMatcherLoader.getDefault()));
6090            var context = or(sslContext, s.sslContext());
6091            if (nn(context))
6092               https = new SSLConnectionSocketFactory(context, protocols, cipherSuites, verifier);
6093            else if (sysProps)
6094               https = new SSLConnectionSocketFactory((javax.net.ssl.SSLSocketFactory)javax.net.ssl.SSLSocketFactory.getDefault(), protocols, cipherSuites, verifier);
6095            else
6096               https = new SSLConnectionSocketFactory(SSLContexts.createDefault(), verifier);
6097         }
6098         return RegistryBuilder.<ConnectionSocketFactory>create()
6099            .register("http", PlainConnectionSocketFactory.getSocketFactory())
6100            .register("https", https)
6101            .build();
6102      }
6103
6104      private static String[] splitSystemProperty(String name) {
6105         var v = System.getProperty(name);
6106         return ib(v) ? null : splita(v);
6107      }
6108
6109      // The pool settings, applied as Apache HttpClientBuilder applies them to its own connection manager.  The
6110      // http.maxConnections limit (default 5) of useSystemProperties() applies per route, and twice that in total,
6111      // unless http.keepAlive is off; maxConnTotal and maxConnPerRoute win over it.  Any limit or a time-to-live
6112      // makes the manager a pooling one: BasicHttpClientConnectionManager has neither.
6113      private PoolSettings poolSettings(HttpClientBuilderSettings s) {
6114         var systemMax = (systemProperties || s.systemProperties()) && "true".equalsIgnoreCase(System.getProperty("http.keepAlive", "true"))
6115            ? Integer.parseInt(System.getProperty("http.maxConnections", "5")) : 0;
6116         var settingsTotal = s.maxConnTotal() > 0 ? s.maxConnTotal() : 2 * systemMax;
6117         var settingsPerRoute = s.maxConnPerRoute() > 0 ? s.maxConnPerRoute() : systemMax;
6118         var maxTotal = maxConnTotal > 0 ? maxConnTotal : settingsTotal;
6119         var maxPerRoute = maxConnPerRoute > 0 ? maxConnPerRoute : settingsPerRoute;
6120         var ownTtl = connTimeToLive > 0;
6121         var ttl = ownTtl ? connTimeToLive : s.connTimeToLive();
6122         var ttlUnit = ownTtl ? connTimeToLiveTimeUnit : s.connTimeToLiveTimeUnit();
6123         var pooling = pooled || maxTotal > 0 || maxPerRoute > 0 || ttl > 0;
6124         return new PoolSettings(pooling, maxTotal, maxPerRoute, ttl, or(ttlUnit, TimeUnit.MILLISECONDS),
6125            or(defaultSocketConfig, s.socketConfig()), or(defaultConnectionConfig, s.connectionConfig()));
6126      }
6127
6128      private static boolean overridesCreateConnectionManager(Class<?> c) {
6129         for (var x = c; x != Builder.class; x = x.getSuperclass()) {
6130            try {
6131               x.getDeclaredMethod("createConnectionManager");
6132               return true;
6133            } catch (@SuppressWarnings("unused") NoSuchMethodException e) { /* Not declared here. */ }
6134         }
6135         return false;
6136      }
6137
6138      // Why guarded @Remote calls cannot be sent through a client built by b, or null if they can.  The checks of the
6139      // client RestClient makes afterwards only see the connection manager the client stores, so they cannot tell:
6140      // - an HttpClientBuilder subclass whose build() or exec-chain factory may build the client around another
6141      //   connection manager or request executor, or put a step in front of them that sends the request elsewhere;
6142      // - an HttpProcessor, which replaces the client's request interceptors (the SSRF guard's lease hand-over and the
6143      //   redirect credential guard among them).
6144      private static String ssrfBuilderRefusal(HttpClientBuilder b) {
6145         var optOut = "or set allowPrivateUrls(true) if this is an intentional local-dev/intranet target.";
6146         if (! HttpClientBuilderSettings.isReadable())
6147            // HTT: only an HttpClient release without the HttpClientBuilder fields, or a JVM that denies reflective access
6148            // to them, gets here (and then the default createConnectionManager() has already failed).
6149            return "Refusing to send a policy-covered @Remote request: the settings of " + HttpClientBuilder.class.getName()
6150               + " cannot be read, so whether the client it built honors the SSRF guardrail's connect-time contract "
6151               + "(pin-on-connect + redirect revalidation) cannot be confirmed.  Use an HttpClient 4.5.x release, " + optOut;
6152         var override = overriddenBuilderMethod(b.getClass());
6153         if (nn(override))
6154            return "Refusing to send a policy-covered @Remote request through a client built by an HttpClientBuilder "
6155               + "subclass (" + override + "): the override may build the client around another connection manager or "
6156               + "request executor, so the SSRF guardrail's connect-time contract (pin-on-connect + redirect "
6157               + "revalidation) cannot be confirmed.  Remove the override (configure the builder through its setters "
6158               + "instead), " + optOut;
6159         if (HttpClientBuilderSettings.hasHttpProcessor(b))
6160            return "Refusing to send a policy-covered @Remote request through a client whose HttpProcessor was set: "
6161               + "httpProcessor(...) replaces the client's request interceptors, among them the SSRF guardrail's own and "
6162               + "the redirect credential guard, so its connect-time contract (pin-on-connect + redirect revalidation) "
6163               + "cannot be confirmed.  Remove the httpProcessor(...) setting (add interceptors with "
6164               + "addInterceptorFirst(...) or addInterceptorLast(...) instead), " + optOut;
6165         var change = lateBuilderChange(b);
6166         if (nn(change))
6167            return "Refusing to send a policy-covered @Remote request through a client whose HttpClientBuilder was changed "
6168               + "after the SSRF guard was wired into it (" + change + "), as an override of createHttpClient() does that "
6169               + "changes the builder after super.createHttpClient() and builds again.  The change may add credentials to "
6170               + "a redirect hop on another origin, follow redirects without revalidation or send the request past the "
6171               + "guard's executor, so the SSRF guardrail's connect-time contract (pin-on-connect + redirect revalidation) "
6172               + "cannot be confirmed.  Make the change before super.createHttpClient() (on httpClientBuilder() or through "
6173               + "this builder's setters), " + optOut;
6174         return null;
6175      }
6176
6177      // What was changed on b after the default createHttpClient() wired the SSRF guard into it, or null if nothing it
6178      // wired was: the guard's two request interceptors must still be the last ones (the redirect credential guard strips
6179      // what every interceptor before it added), and its redirect strategy and request executor must still be set.
6180      private static String lateBuilderChange(HttpClientBuilder b) {
6181         var last = HttpClientBuilderSettings.lastRequestInterceptors(b);
6182         var n = last.size();
6183         if (n < 2 || ! (last.get(n - 2) instanceof ClassicRedirectCredentialGuard) || ! (last.get(n - 1) instanceof SsrfGuardConnectionManager.GuardInterceptor))
6184            return "a request interceptor was added after the SSRF guard's own";
6185         if (! (HttpClientBuilderSettings.redirectStrategy(b) instanceof PolicyAwareRedirectStrategy))
6186            return "the redirect strategy was replaced";
6187         if (! (HttpClientBuilderSettings.requestExecutor(b) instanceof SsrfGuardConnectionManager.GuardedRequestExecutor))
6188            return "the request executor was replaced";
6189         return null;
6190      }
6191
6192      // The HttpClientBuilder methods that decide which connection manager and request executor a built client uses.
6193      private static final List<Method> BUILDER_EXEC_METHODS = Arrays.stream(HttpClientBuilder.class.getDeclaredMethods())
6194         .filter(m -> Set.of("build", "createMainExec", "decorateMainExec", "decorateProtocolExec").contains(m.getName()))
6195         .toList();
6196
6197      // Returns "<class> overrides <method>(<params>)" for the first of BUILDER_EXEC_METHODS a class between c and
6198      // HttpClientBuilder declares, or null if there is none.
6199      private static String overriddenBuilderMethod(Class<?> c) {
6200         for (var x = c; nn(x) && x != HttpClientBuilder.class; x = x.getSuperclass()) {
6201            for (var m : BUILDER_EXEC_METHODS) {
6202               try {
6203                  x.getDeclaredMethod(m.getName(), m.getParameterTypes());
6204                  return cn(x) + " overrides " + m.getName() + "(" + String.join(",", Arrays.stream(m.getParameterTypes()).map(Class::getSimpleName).toList()) + ")";
6205               } catch (@SuppressWarnings("unused") NoSuchMethodException e) { /* Not declared here. */ }
6206            }
6207         }
6208         return null;
6209      }
6210
6211      private static HttpClientConnectionManager newConnectionManager(Registry<ConnectionSocketFactory> registry, DnsResolver dnsResolver, PoolSettings p) {
6212         if (! p.pooling()) {
6213            var cm = new BasicHttpClientConnectionManager(registry, null, null, dnsResolver);
6214            if (nn(p.socketConfig()))
6215               cm.setSocketConfig(p.socketConfig());
6216            if (nn(p.connectionConfig()))
6217               cm.setConnectionConfig(p.connectionConfig());
6218            return cm;
6219         }
6220         var cm = new PoolingHttpClientConnectionManager(registry, null, null, dnsResolver, p.timeToLive(), p.timeToLiveUnit());
6221         if (nn(p.socketConfig()))
6222            cm.setDefaultSocketConfig(p.socketConfig());
6223         if (nn(p.connectionConfig()))
6224            cm.setDefaultConnectionConfig(p.connectionConfig());
6225         if (p.maxTotal() > 0)
6226            cm.setMaxTotal(p.maxTotal());
6227         if (p.maxPerRoute() > 0)
6228            cm.setDefaultMaxPerRoute(p.maxPerRoute());
6229         return cm;
6230      }
6231
6232      // The settings both pools of the default connection manager are built with.
6233      private record PoolSettings(boolean pooling, int maxTotal, int maxPerRoute, long timeToLive, TimeUnit timeToLiveUnit,
6234         SocketConfig socketConfig, ConnectionConfig connectionConfig) {}
6235
6236      /**
6237       * Creates the builder for the form data list.
6238       *
6239       * <p>
6240       * Subclasses can override this method to provide their own implementation.
6241       *
6242       * <p>
6243       * The default behavior creates an empty builder.
6244       *
6245       * @return The form data list builder.
6246       * @see #formData()
6247       */
6248      protected PartList createFormData() {
6249         return PartList.create();
6250      }
6251
6252      /**
6253       * Creates the builder for the header list.
6254       *
6255       * <p>
6256       * Subclasses can override this method to provide their own implementation.
6257       *
6258       * <p>
6259       * The default behavior creates an empty builder.
6260       *
6261       * @return The header list builder.
6262       * @see #headers()
6263       */
6264      protected HeaderList createHeaderData() {
6265         return HeaderList.create();
6266      }
6267
6268      /**
6269       * Creates an instance of an {@link HttpClient} to be used to handle all HTTP communications with the target server.
6270       *
6271       * <p>
6272       * This HTTP client is used when the HTTP client is not specified through one of the constructors or the
6273       * {@link #httpClient(CloseableHttpClient)} method.
6274       *
6275       * <p>
6276       * Subclasses can override this method to provide specially-configured HTTP clients to handle stuff such as
6277       * SSL/TLS certificate handling, authentication, etc.
6278       *
6279       * <p>
6280       * The default implementation returns an instance of {@link HttpClient} using the client builder returned by
6281       * {@link #createHttpClientBuilder()}.
6282       *
6283       * <h5 class='section'>Notes:</h5><ul>
6284       *    <li class='warn'>SSRF-guard-active {@code @Remote} calls (ones without the
6285       *       {@link #allowPrivateUrls(boolean) allowPrivateUrls} opt-in) are only sent through the client this default
6286       *       implementation builds, which it wires to the connection manager that pins them.  The client refuses every
6287       *       such call if an override returns any other client (including a wrapper around the one it built), or after
6288       *       {@code super.createHttpClient()} sets an {@link HttpProcessor} on the {@link HttpClientBuilder}, adds a request
6289       *       interceptor with {@code addInterceptorLast(...)}, or replaces its redirect strategy or request executor (make
6290       *       such changes before calling {@code super}), or if the builder is a
6291       *       subclass that overrides {@link HttpClientBuilder#build()} or one of its exec-chain methods
6292       *       ({@code createMainExec}, {@code decorateMainExec}, {@code decorateProtocolExec}), even an override that
6293       *       returns or decorates nothing but what {@code super} built.  Ordinary requests are unaffected.
6294       * </ul>
6295       *
6296       * <h5 class='section'>Example:</h5>
6297       * <p class='bjava'>
6298       *    <jc>// A Builder that provides it's own customized HttpClient.</jc>
6299       *    <jk>public class</jk> MyBuilder <jk>extends</jk> Builder {
6300       *       <ja>@Override</ja>
6301       *       <jk>protected</jk> HttpClientBuilder createHttpClient() {
6302       *          <jk>return</jk> HttpClientBuilder.<jsm>create</jsm>().build();
6303       *       }
6304       *    }
6305       *
6306       *    <jc>// Instantiate.</jc>
6307       *    RestClient <jv>client</jv> = <jk>new</jk> MyBuilder().build();
6308       * </p>
6309       *
6310       * @return The HTTP client to use.
6311       */
6312      protected CloseableHttpClient createHttpClient() {
6313         // A new connection manager for each client unless the caller supplied one: closing a client shuts its
6314         // connection manager down, so a reused builder must not hand an earlier client's to the next one.
6315         var cm = nn(connectionManager) ? connectionManager : createConnectionManager();
6316         // Only a connection manager this builder created can be given a pinned twin; for any other one, the client
6317         // reports the SSRF guard as unsupported and refuses guarded remote calls.  The twin is built from the same
6318         // socket factories and pool settings as the connection manager, so it is the same kind; settings an
6319         // override applied to that instance afterwards reach it before each guarded lease.
6320         ssrfGuard = nn(cm) && cm == defaultConnectionManager ? new SsrfGuardConnectionManager(cm, newConnectionManager(defaultRegistry, pinningResolver(), defaultPoolSettings)) : null;
6321         ownsConnectionManager = nn(ssrfGuard) && connectionManager == null && ! overridesCreateConnectionManager(getClass());
6322         if (nn(ssrfGuard))
6323            cm = ssrfGuard;
6324         httpClientBuilder().setConnectionManager(cm);
6325         // Once per HttpClientBuilder: a builder reused after build() keeps the interceptors earlier builds added.
6326         if (! HttpClientBuilderSettings.hasLastRequestInterceptor(httpClientBuilder(), ClassicRedirectCredentialGuard.class))
6327            httpClientBuilder().addInterceptorLast(new ClassicRedirectCredentialGuard());
6328         if (nn(ssrfGuard) && HttpClientBuilderSettings.isReadable()) {
6329            // The guard of a request travels on its context (see SsrfGuardMarker): the interceptor reads it before the
6330            // connection lease, and the executor refuses a guarded request on a connection of the ordinary pool.
6331            if (! HttpClientBuilderSettings.hasLastRequestInterceptor(httpClientBuilder(), SsrfGuardConnectionManager.GuardInterceptor.class))
6332               httpClientBuilder().addInterceptorLast(new SsrfGuardConnectionManager.GuardInterceptor());
6333            httpClientBuilder().setRequestExecutor(new SsrfGuardConnectionManager.GuardedRequestExecutor(HttpClientBuilderSettings.requestExecutor(httpClientBuilder()), ssrfGuard));
6334         }
6335         httpClientBuilder().setRedirectStrategy(new PolicyAwareRedirectStrategy());
6336         return httpClientBuilder().build();
6337      }
6338
6339      // The shared pinning resolver unless this builder set per-client allowed address ranges, which need a resolver of their own.
6340      private PolicyPinningDnsResolver pinningResolver() {
6341         var ranges = RemoteUrlPolicy.AllowedRanges.of(allowedAddressRanges.toArray(new String[0]));
6342         return ranges.isEmpty() ? PolicyPinningDnsResolver.INSTANCE : new PolicyPinningDnsResolver(ranges);
6343      }
6344
6345      /**
6346       * Creates an instance of an {@link HttpClientBuilder} to be used to create the {@link HttpClient}.
6347       *
6348       * <p>
6349       * Subclasses can override this method to provide their own client builder.
6350       * The builder can also be specified using the {@link #httpClientBuilder(HttpClientBuilder)} method.
6351       *
6352       * <h5 class='section'>Example:</h5>
6353       * <p class='bjava'>
6354       *    <jc>// A Builder that provides it's own customized HttpClientBuilder.</jc>
6355       *    <jk>public class</jk> MyBuilder <jk>extends</jk> Builder {
6356       *       <ja>@Override</ja>
6357       *       <jk>protected</jk> HttpClientBuilder createHttpClientBuilder() {
6358       *          <jk>return</jk> HttpClientBuilder.<jsm>create</jsm>();
6359       *       }
6360       *    }
6361       *
6362       *    <jc>// Instantiate.</jc>
6363       *    RestClient <jv>client</jv> = <jk>new</jk> MyBuilder().build();
6364       * </p>
6365       *
6366       * @return The HTTP client builder to use to create the HTTP client.
6367       */
6368      protected HttpClientBuilder createHttpClientBuilder() {
6369         return HttpClientBuilder.create();
6370      }
6371
6372      /**
6373       * Instantiates the parser group sub-builder.
6374       *
6375       * @return A new parser group sub-builder.
6376       */
6377      protected ParserSet.Builder createParsers() {
6378         return ParserSet.create().marshallingContext(marshallingContext());
6379      }
6380
6381      /**
6382       * Instantiates the part parser sub-builder.
6383       *
6384       * @return A new part parser sub-builder.
6385       */
6386      protected HttpPartParser.Creator createPartParser() {
6387         return HttpPartParser.creator().type(OpenApiParser.class).marshallingContext(marshallingContext());
6388      }
6389
6390      /**
6391       * Instantiates the part serializer sub-builder.
6392       *
6393       * @return A new part serializer sub-builder.
6394       */
6395      protected HttpPartSerializer.Creator createPartSerializer() {
6396         return HttpPartSerializer.creator().type(OpenApiSerializer.class).marshallingContext(marshallingContext());
6397      }
6398
6399      /**
6400       * Creates the builder for the path data list.
6401       *
6402       * <p>
6403       * Subclasses can override this method to provide their own implementation.
6404       *
6405       * <p>
6406       * The default behavior creates an empty builder.
6407       *
6408       * @return The path data list builder.
6409       * @see #pathData()
6410       */
6411      protected PartList createPathData() {
6412         return PartList.create();
6413      }
6414
6415      /**
6416       * Creates the builder for the query data list.
6417       *
6418       * <p>
6419       * Subclasses can override this method to provide their own implementation.
6420       *
6421       * <p>
6422       * The default behavior creates an empty builder.
6423       *
6424       * @return The query data list builder.
6425       * @see #queryData()
6426       */
6427      protected PartList createQueryData() {
6428         return PartList.create();
6429      }
6430
6431      /**
6432       * Instantiates the serializer group sub-builder.
6433       *
6434       * @return A new serializer group sub-builder.
6435       */
6436      protected SerializerSet.Builder createSerializers() {
6437         return SerializerSet.create().marshallingContext(marshallingContext());
6438      }
6439
6440      /**
6441       * Instantiates the URL-encoding serializer sub-builder.
6442       *
6443       * @return A new URL-encoding serializer sub-builder.
6444       */
6445      protected UrlEncodingSerializer.Builder createUrlEncodingSerializer() {
6446         return UrlEncodingSerializer.create().marshallingContext(marshallingContext());
6447      }
6448
6449      final CloseableHttpClient getHttpClient() { return nn(httpClient) ? httpClient : createHttpClient(); }
6450   }
6451
6452   /**
6453    * Concrete default builder leaf for the non-subclassed {@link RestClient#create()} / {@link RestClient#copy()} path.
6454    */
6455   public static final class DefaultBuilder extends Builder<DefaultBuilder> {
6456
6457      DefaultBuilder() {}
6458   }
6459
6460   private static final RestCallInterceptor[] EMPTY_REST_CALL_INTERCEPTORS = {};
6461   private static final ConcurrentHashMap<Class<?>,Context> requestContexts = new ConcurrentHashMap<>();
6462   private static final BiPredicate<RestRequest,RestResponse> LOG_REQUESTS_PREDICATE_DEFAULT = (req, res) -> true;
6463
6464   /**
6465    * Instantiates a new clean-slate {@link Builder} object.
6466    *
6467    * @return A new {@link Builder} object.
6468    */
6469   public static <T extends Builder<T>> Builder<T> create() {
6470      return (Builder<T>) new DefaultBuilder();
6471   }
6472
6473   protected final boolean detectLeaks;
6474   protected final boolean allowPrivateUrls;
6475   private final RemoteUrlPolicy.AllowedRanges allowedAddressRanges;
6476   protected final boolean ignoreErrors;
6477   protected final boolean keepHttpClientOpen;
6478   protected final boolean skipEmptyFormData;
6479   protected final boolean skipEmptyHeaderData;
6480   protected final boolean skipEmptyQueryData;
6481   protected final BiPredicate<RestRequest,RestResponse> logRequestsPredicate;
6482   protected final CloseableHttpClient httpClient;
6483   protected final DetailLevel logRequests;
6484   protected final HeaderList headerData;
6485   protected final HttpPartParser partParser;
6486   protected final HttpPartSerializer partSerializer;
6487   protected final Level logRequestsLevel;
6488   protected final PartList formData;
6489   protected final PartList pathData;
6490   protected final PartList queryData;
6491   protected final ParserSet parsers;
6492   protected final RestCallInterceptor[] interceptors;
6493   protected final SerializerSet serializers;
6494   protected final UrlEncodingSerializer urlEncodingSerializer;  // Used for form posts only.
6495   Predicate<Integer> errorCodes;
6496   private final WritableBeanStore beanStore;
6497   private final HttpClientConnectionManager connectionManager;
6498   private final Logger logger;
6499   private final Map<Class<?>,HttpPartParser> partParsers = new ConcurrentHashMap<>();
6500   private final Map<Class<?>,HttpPartSerializer> partSerializers = new ConcurrentHashMap<>();
6501   private final Pattern absUrlPattern = Pattern.compile("^\\w++://.*");
6502   private final PrintStream console;
6503   private final RestCallHandler callHandler;
6504   private StackTraceElement[] closedStack;
6505   private final StackTraceElement[] creationStack;
6506   private final Supplier<String> rootUrl;
6507   private final boolean executorServiceShutdownOnClose;
6508   private final boolean logToConsole;
6509   private final boolean ssrfPolicySupported;
6510
6511   // Why SSRF-guard-active @Remote calls are refused, or null if they are supported.
6512   private final String ssrfRefusal;
6513   // The two-pool router this client's HttpClient uses, or null when the SSRF guard is unsupported.
6514   private final SsrfGuardConnectionManager ssrfGuard;
6515
6516   private final boolean ownsConnectionManager;
6517   private final AtomicBoolean isClosed = new AtomicBoolean(false);
6518   private final AtomicReference<ExecutorService> executorService = new AtomicReference<>();
6519
6520   /**
6521    * Constructor.
6522    *
6523    * @param builder The builder for this client.
6524    */
6525   public RestClient(Builder<?> builder) {
6526      super(builder);
6527
6528      beanStore = builder.beanStore.addBean(RestClient.class, this);
6529
6530      callHandler = builder.callHandler().run();
6531      connectionManager = builder.connectionManager;
6532      console = nn(builder.console) ? builder.console : System.err;
6533      creationStack = isDebug() ? Thread.currentThread().getStackTrace() : null;
6534      detectLeaks = builder.detectLeaks;
6535      allowPrivateUrls = builder.allowPrivateUrls || Boolean.getBoolean(RemoteUrlPolicy.ALLOW_PRIVATE_URLS_PROPERTY);
6536      allowedAddressRanges = RemoteUrlPolicy.AllowedRanges.of(builder.allowedAddressRanges.toArray(new String[0]));
6537      errorCodes = builder.errorCodes;
6538      formData = builder.formData().copy();
6539      headerData = builder.headers().copy();
6540      httpClient = builder.getHttpClient();
6541      // Read after getHttpClient(): the default createHttpClient() sets ssrfGuard.  It wires it into the client it
6542      // builds, but an override of createHttpClient() or of HttpClientBuilder.build() may return another client.
6543      var builtGuard = builder.httpClient == null ? builder.ssrfGuard : null;
6544      ssrfGuard = nn(builtGuard) && builtGuard.isConnectionManagerOf(httpClient) ? builtGuard : null;
6545      ownsConnectionManager = nn(ssrfGuard) && builder.ownsConnectionManager;
6546      // The HttpClientBuilder is checked as it is now, not when the default createHttpClient() built from it: an override
6547      // may call super, change the builder and build again.  What is checked: a builder subclass override, an
6548      // HttpProcessor, and whether what createHttpClient() wired (the guard's interceptors last, its redirect strategy and
6549      // request executor) is still in place.  One of these changes made after the client was built is refused too (fail
6550      // closed): which client it went into cannot be told.  A change undone before the override returns is not seen.
6551      ssrfRefusal = ssrfRefusal(builtGuard, nn(builtGuard) ? Builder.ssrfBuilderRefusal(builder.httpClientBuilder()) : null);
6552      ssrfPolicySupported = ssrfRefusal == null;
6553      ignoreErrors = builder.ignoreErrors;
6554      interceptors = nn(builder.interceptors) ? builder.interceptors.toArray(EMPTY_REST_CALL_INTERCEPTORS) : EMPTY_REST_CALL_INTERCEPTORS;
6555      keepHttpClientOpen = builder.keepHttpClientOpen;
6556      logger = nn(builder.logger) ? builder.logger : Logger.getLogger(cn(RestClient.class));
6557      if (nn(builder.logRequests)) {
6558         logRequests = builder.logRequests;
6559      } else {
6560         logRequests = isDebug() ? DetailLevel.FULL : DetailLevel.NONE;
6561      }
6562      if (nn(builder.logRequestsLevel)) {
6563         logRequestsLevel = builder.logRequestsLevel;
6564      } else {
6565         logRequestsLevel = isDebug() ? Level.WARNING : Level.OFF;
6566      }
6567      logRequestsPredicate = nn(builder.logRequestsPredicate) ? builder.logRequestsPredicate : LOG_REQUESTS_PREDICATE_DEFAULT;
6568      logToConsole = builder.logToConsole || isDebug();
6569      parsers = builder.parsers().build();
6570      partParser = builder.partParser().create();
6571      partSerializer = builder.partSerializer().create();
6572      pathData = builder.pathData().copy();
6573      queryData = builder.queryData().copy();
6574      rootUrl = builder.rootUrl;
6575      serializers = builder.serializers().build();
6576      skipEmptyFormData = builder.skipEmptyFormData;
6577      skipEmptyHeaderData = builder.skipEmptyHeaderData;
6578      skipEmptyQueryData = builder.skipEmptyQueryData;
6579      urlEncodingSerializer = builder.urlEncodingSerializer().build();
6580      if (builder.executorService != null)
6581         executorService.set(builder.executorService);
6582      executorServiceShutdownOnClose = builder.executorServiceShutdownOnClose;
6583
6584      init();
6585   }
6586
6587   /**
6588    * Returns the root URL set on this client.
6589    *
6590    * @return The root URL, or <jk>null</jk> if not set.
6591    */
6592   public String getRootUrl() {
6593      return rootUrl != null ? rootUrl.get() : null;
6594   }
6595
6596   /**
6597    * Returns the effective builder/settings-level {@code allowPrivateUrls} opt-in for this client (the logical OR
6598    * of {@code Builder#allowPrivateUrls(boolean)} and the {@value RemoteUrlPolicy#ALLOW_PRIVATE_URLS_PROPERTY}
6599    * system property).
6600    *
6601    * <p>
6602    * The fully effective per-call value additionally ORs in the {@code @Remote}/{@code @RemoteOp}
6603    * {@code allowPrivateUrls} annotation attribute (see {@link Remote#allowPrivateUrls()}).
6604    *
6605    * @return {@code true} if this client opts into allowing private/loopback/link-local/metadata {@code @Remote} targets.
6606    */
6607   public boolean isAllowPrivateUrls() {
6608      return allowPrivateUrls;
6609   }
6610
6611   /**
6612    * Returns the per-client allowed address ranges set through {@link Builder#allowAddressRanges(String...)}.
6613    *
6614    * @return The ranges; never <jk>null</jk>, empty when none were set.
6615    */
6616   public RemoteUrlPolicy.AllowedRanges getAllowedAddressRanges() {
6617      return allowedAddressRanges;
6618   }
6619
6620   /**
6621    * Performs a REST call where the entire call is specified in a simple string.
6622    *
6623    * <p>
6624    * This method is useful for performing callbacks when the target of a callback is passed in
6625    * on an initial request, for example to signal when a long-running process has completed.
6626    *
6627    * <p>
6628    * The call string can be any of the following formats:
6629    * <ul class='spaced-list'>
6630    *    <li>
6631    *       <js>"[method] [uri]"</js> - e.g. <js>"GET http://localhost/callback"</js>
6632    *    <li>
6633    *       <js>"[method] [uri] [payload]"</js> - e.g. <js>"POST http://localhost/callback some text payload"</js>
6634    *    <li>
6635    *       <js>"[method] [headers] [uri] [payload]"</js> - e.g. <js>"POST {'Content-Type':'text/json'} http://localhost/callback {'some':'json'}"</js>
6636    * </ul>
6637    * <p>
6638    * The payload will always be sent using a simple {@link StringEntity}.
6639    *
6640    * @param callString The call string.
6641    *    <br>Can be <jk>null</jk> or empty (treated as empty string, will result in an invalid request).
6642    * @return
6643    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
6644    *    as a parsed object.
6645    * @throws RestCallException REST call failed.
6646    */
6647   @SuppressWarnings({
6648      "java:S1854", // state = S5 is a necessary state machine transition; SonarLint false positive
6649      "java:S4165" // state already holds S5 in some paths, but the assignment is a deliberate state machine transition
6650   })
6651   public RestRequest callback(String callString) throws RestCallException {
6652      callString = emptyIfNull(callString);
6653
6654      // S1 - Looking for end of method.
6655      // S2 - Found end of method, looking for beginning of URI or headers.
6656      // S3 - Found beginning of headers, looking for end of headers.
6657      // S4 - Found end of headers, looking for beginning of URI.
6658      // S5 - Found beginning of URI, looking for end of URI.
6659
6660      var state = S1;
6661
6662      var mark = 0;
6663      String method = null;
6664      String headers = null;
6665      String uri = null;
6666      String content = null;
6667      for (var i = 0; i < callString.length(); i++) {
6668         var c = callString.charAt(i);
6669         if (state == S1) {
6670            if (isWhitespace(c)) {
6671               method = callString.substring(mark, i);
6672               state = S2;
6673            }
6674         } else if (state == S2) {
6675            if (! isWhitespace(c)) {
6676               mark = i;
6677               state = (c == '{') ? S3 : S5;
6678            }
6679         } else if (state == S3) {
6680            if (c == '}') {
6681               headers = callString.substring(mark, i + 1);
6682               state = S4;
6683            }
6684         } else if (state == S4) {
6685            if (! isWhitespace(c)) {
6686               mark = i;
6687               state = S5;
6688            }
6689         } else /* (state == S5) */ {
6690            if (isWhitespace(c)) {
6691               uri = callString.substring(mark, i);
6692               content = callString.substring(i).trim();
6693               break;
6694            }
6695         }
6696      }
6697
6698      if (state != S5)
6699         throw new RestCallException(null, null, "Invalid format for call string.  State=%s", state);
6700
6701      try {
6702         var req = request(method, uri, ine(content));
6703         if (nn(headers))
6704            Json5Map.ofString(headers).forEach((k, v) -> req.header(stringHeader(k, s(v))));
6705         if (ine(content))
6706            req.contentString(content);
6707         return req;
6708      } catch (ParseException e) {
6709         throw new RestCallException(null, e, "Invalid format for call string.");
6710      }
6711   }
6712
6713   /**
6714    * Calls {@link CloseableHttpClient#close()} on the underlying {@link CloseableHttpClient}.
6715    *
6716    * <p>
6717    * It's good practice to call this method after the client is no longer used.
6718    *
6719    * @throws IOException Thrown by underlying stream.
6720    */
6721   @Override
6722   public void close() throws IOException {
6723      isClosed.set(true);
6724      ExecutorService es = executorService.get();
6725      if (! keepHttpClientOpen) {
6726         try {
6727            httpClient.close();
6728         } finally {
6729            shutdownPinnedPool();
6730         }
6731      }
6732      if (nn(es) && executorServiceShutdownOnClose)
6733         es.shutdown();
6734      // If executorServiceShutdownOnClose is false, executor service remains open for reuse
6735      if (nn(creationStack))
6736         closedStack = Thread.currentThread().getStackTrace();
6737   }
6738
6739   // The pinned pool is always this client's own (nothing else can reach it), and so is the ordinary pool when this
6740   // client's build() created it, so they are shut down with the client even when the connection manager is shared
6741   // and the HttpClient therefore leaves it open.
6742   private void shutdownPinnedPool() {
6743      if (ownsConnectionManager)
6744         ssrfGuard.shutdown();
6745      else if (nn(ssrfGuard))
6746         ssrfGuard.shutdownPinned();
6747   }
6748
6749   /**
6750    * Same as {@link #close()}, but ignores any exceptions.
6751    */
6752   public void closeQuietly() {
6753      isClosed.set(true);
6754      try {
6755         if (! keepHttpClientOpen) {
6756            try {
6757               httpClient.close();
6758            } finally {
6759               shutdownPinnedPool();
6760            }
6761         }
6762         ExecutorService es = executorService.get();
6763         if (nn(es) && executorServiceShutdownOnClose)
6764            es.shutdown();
6765      } catch (@SuppressWarnings("unused") Exception t) { /* Suppress close/shutdown exceptions during cleanup */ }
6766      if (nn(creationStack))
6767         closedStack = Thread.currentThread().getStackTrace();
6768   }
6769
6770   @Override /* Overridden from Context */
6771   public Builder copy() {
6772      throw new NoSuchMethodError("Not implemented.");
6773   }
6774
6775   /**
6776    * Creates a mutable copy of the form data defined on this client.
6777    *
6778    * <p>
6779    * Used during the construction of {@link RestRequest} objects.
6780    *
6781    * <p>
6782    * Subclasses can override this method to provide their own builder.
6783    *
6784    * @return A new builder.
6785    */
6786   public PartList createFormData() {
6787      return formData.copy();
6788   }
6789
6790   /**
6791    * Creates a mutable copy of the header data defined on this client.
6792    *
6793    * <p>
6794    * Used during the construction of {@link RestRequest} objects.
6795    *
6796    * <p>
6797    * Subclasses can override this method to provide their own builder.
6798    *
6799    * @return A new builder.
6800    */
6801   public HeaderList createHeaderData() {
6802      return headerData.copy();
6803   }
6804
6805   /**
6806    * Creates a mutable copy of the path data defined on this client.
6807    *
6808    * <p>
6809    * Used during the construction of {@link RestRequest} objects.
6810    *
6811    * <p>
6812    * Subclasses can override this method to provide their own builder.
6813    *
6814    * @return A new builder.
6815    */
6816   public PartList createPathData() {
6817      return pathData.copy();
6818   }
6819
6820   /**
6821    * Creates a mutable copy of the query data defined on this client.
6822    *
6823    * <p>
6824    * Used during the construction of {@link RestRequest} objects.
6825    *
6826    * <p>
6827    * Subclasses can override this method to provide their own builder.
6828    *
6829    * @return A new builder.
6830    */
6831   public PartList createQueryData() {
6832      return queryData.copy();
6833   }
6834
6835   /**
6836    * Perform a <c>DELETE</c> request against the specified URI.
6837    *
6838    * @param uri
6839    *    The URI of the remote REST resource.
6840    *    <br>Can be any of the following types:
6841    *    <ul>
6842    *       <li>{@link URIBuilder}
6843    *       <li>{@link URI}
6844    *       <li>{@link URL}
6845    *       <li>{@link String}
6846    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
6847    *    </ul>
6848    * @return
6849    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
6850    *    as a parsed object.
6851    * @throws RestCallException If any authentication errors occurred.
6852    */
6853   public RestRequest delete(Object uri) throws RestCallException {
6854      return request(op("DELETE", uri, NO_BODY));
6855   }
6856
6857   /**
6858    * Executes HTTP request using the default context.
6859    *
6860    * <h5 class='section'>Notes:</h5><ul>
6861    *    <li class='note'>This method gets passed on directly to the underlying {@link HttpClient} class.
6862    * </ul>
6863    *
6864    * @param target The target host for the request.
6865    *    <br>Implementations may accept <jk>null</jk> if they can still determine a route, for example to a default
6866    *       target or by inspecting the request.
6867    * @param request The request to execute.
6868    * @return The response to the request.
6869    *    <br>This is always a final response, never an intermediate response with an 1xx status code.
6870    *    <br>Whether redirects or authentication challenges will be returned or handled automatically depends on the
6871    *       implementation and configuration of this client.
6872    * @throws IOException In case of a problem or the connection was aborted.
6873    * @throws ClientProtocolException In case of an http protocol error.
6874    */
6875   @Override /* Overridden from HttpClient */
6876   public HttpResponse execute(HttpHost target, HttpRequest request) throws IOException {
6877      return httpClient.execute(target, request);
6878   }
6879
6880   /**
6881    * Executes HTTP request using the given context.
6882    *
6883    * <h5 class='section'>Notes:</h5><ul>
6884    *    <li class='note'>This method gets passed on directly to the underlying {@link HttpClient} class.
6885    *    <li class='note'>The {@link #run(HttpHost,HttpRequest,HttpContext)} method has been provided as a wrapper around this method.
6886    *       Subclasses can override these methods for handling requests with and without bodies separately.
6887    *    <li class='note'>The {@link RestCallHandler} interface can also be implemented to intercept this method.
6888    * </ul>
6889    *
6890    * @param target The target host for the request.
6891    *    <br>Implementations may accept <jk>null</jk> if they can still determine a route, for example to a default
6892    *       target or by inspecting the request.
6893    * @param request The request to execute.
6894    * @param context The context to use for the execution, or <jk>null</jk> to use the default context.
6895    * @return
6896    *    The response to the request.
6897    *    <br>This is always a final response, never an intermediate response with an 1xx status code.
6898    *    <br>Whether redirects or authentication challenges will be returned or handled automatically depends on the
6899    *       implementation and configuration of this client.
6900    * @throws IOException In case of a problem or the connection was aborted.
6901    * @throws ClientProtocolException In case of an http protocol error.
6902    */
6903   @Override /* Overridden from HttpClient */
6904   public HttpResponse execute(HttpHost target, HttpRequest request, HttpContext context) throws IOException {
6905      return httpClient.execute(target, request, context);
6906   }
6907
6908   /**
6909    * Executes HTTP request to the target using the default context and processes the response using the given response handler.
6910    *
6911    * <p>
6912    * The content entity associated with the response is fully consumed and the underlying connection is released back
6913    * to the connection manager automatically in all cases relieving individual {@link ResponseHandler ResponseHandlers}
6914    * from having to manage resource deallocation internally.
6915    *
6916    * <h5 class='section'>Notes:</h5><ul>
6917    *    <li class='note'>This method gets passed on directly to the underlying {@link HttpClient} class.
6918    * </ul>
6919    *
6920    * @param target
6921    *    The target host for the request.
6922    *    <br>Implementations may accept <jk>null</jk> if they can still determine a route, for example to a default target or by inspecting the request.
6923    * @param request The request to execute.
6924    * @param responseHandler The response handler.
6925    * @return The response object as generated by the response handler.
6926    * @throws IOException In case of a problem or the connection was aborted.
6927    * @throws ClientProtocolException In case of an http protocol error.
6928    */
6929   @Override /* Overridden from HttpClient */
6930   public <T> T execute(HttpHost target, HttpRequest request, ResponseHandler<? extends T> responseHandler) throws IOException {
6931      return httpClient.execute(target, request, responseHandler);
6932   }
6933
6934   /**
6935    * Executes a request using the default context and processes the response using the given response handler.
6936    *
6937    * <p>
6938    * The content entity associated with the response is fully consumed and the underlying connection is released back
6939    * to the connection manager automatically in all cases relieving individual {@link ResponseHandler ResponseHandlers}
6940    * from having to manage resource deallocation internally.
6941    *
6942    * <h5 class='section'>Notes:</h5><ul>
6943    *    <li class='note'>This method gets passed on directly to the underlying {@link HttpClient} class.
6944    * </ul>
6945    *
6946    * @param target
6947    *    The target host for the request.
6948    *    <br>Implementations may accept <jk>null</jk> if they can still determine a route, for example to a default target or by inspecting the request.
6949    * @param request The request to execute.
6950    * @param responseHandler The response handler.
6951    * @param context The context to use for the execution, or <jk>null</jk> to use the default context.
6952    * @return The response object as generated by the response handler.
6953    * @throws IOException In case of a problem or the connection was aborted.
6954    * @throws ClientProtocolException In case of an http protocol error.
6955    */
6956   @Override /* Overridden from HttpClient */
6957   public <T> T execute(HttpHost target, HttpRequest request, ResponseHandler<? extends T> responseHandler, HttpContext context) throws IOException {
6958      return httpClient.execute(target, request, responseHandler, context);
6959   }
6960
6961   /**
6962    * Executes HTTP request using the default context.
6963    *
6964    * <h5 class='section'>Notes:</h5><ul>
6965    *    <li class='note'>This method gets passed on directly to the underlying {@link HttpClient} class.
6966    * </ul>
6967    *
6968    * @param request The request to execute.
6969    * @return
6970    *    The response to the request.
6971    *    <br>This is always a final response, never an intermediate response with an 1xx status code.
6972    *    <br>Whether redirects or authentication challenges will be returned or handled automatically depends on the
6973    *       implementation and configuration of this client.
6974    * @throws IOException In case of a problem or the connection was aborted.
6975    * @throws ClientProtocolException In case of an http protocol error.
6976    */
6977   @Override /* Overridden from HttpClient */
6978   public HttpResponse execute(HttpUriRequest request) throws IOException {
6979      return httpClient.execute(request);
6980   }
6981
6982   /**
6983    * Executes HTTP request using the given context.
6984    *
6985    * <h5 class='section'>Notes:</h5><ul>
6986    *    <li class='note'>This method gets passed on directly to the underlying {@link HttpClient} class.
6987    * </ul>
6988    *
6989    * @param request The request to execute.
6990    * @param context The context to use for the execution, or <jk>null</jk> to use the default context.
6991    * @return
6992    *    The response to the request.
6993    *    <br>This is always a final response, never an intermediate response with an 1xx status code.
6994    *    <br>Whether redirects or authentication challenges will be returned or handled automatically depends on the
6995    *       implementation and configuration of this client.
6996    * @throws IOException In case of a problem or the connection was aborted.
6997    * @throws ClientProtocolException In case of an http protocol error.
6998    */
6999   @Override /* Overridden from HttpClient */
7000   public HttpResponse execute(HttpUriRequest request, HttpContext context) throws IOException {
7001      return httpClient.execute(request, context);
7002   }
7003
7004   /**
7005    * Executes HTTP request using the default context and processes the response using the given response handler.
7006    *
7007    * <p>
7008    * The content entity associated with the response is fully consumed and the underlying connection is released back
7009    * to the connection manager automatically in all cases relieving individual {@link ResponseHandler ResponseHandlers}
7010    * from having to manage resource deallocation internally.
7011    *
7012    * <h5 class='section'>Notes:</h5><ul>
7013    *    <li class='note'>This method gets passed on directly to the underlying {@link HttpClient} class.
7014    * </ul>
7015    *
7016    * @param request The request to execute.
7017    * @param responseHandler The response handler.
7018    * @return Object returned by response handler.
7019    * @throws IOException In case of a problem or the connection was aborted.
7020    * @throws ClientProtocolException In case of an http protocol error.
7021    */
7022   @Override /* Overridden from HttpClient */
7023   public <T> T execute(HttpUriRequest request, ResponseHandler<? extends T> responseHandler) throws IOException {
7024      return httpClient.execute(request, responseHandler);
7025   }
7026
7027   /**
7028    * Executes HTTP request using the given context and processes the response using the given response handler.
7029    *
7030    * <p>
7031    * The content entity associated with the response is fully consumed and the underlying connection is released back
7032    * to the connection manager automatically in all cases relieving individual {@link ResponseHandler ResponseHandlers}
7033    * from having to manage resource deallocation internally.
7034    *
7035    * <h5 class='section'>Notes:</h5><ul>
7036    *    <li class='note'>This method gets passed on directly to the underlying {@link HttpClient} class.
7037    * </ul>
7038    *
7039    * @param request The request to execute.
7040    * @param responseHandler The response handler.
7041    * @param context The context to use for the execution, or <jk>null</jk> to use the default context.
7042    * @return The response object as generated by the response handler.
7043    * @throws IOException In case of a problem or the connection was aborted.
7044    * @throws ClientProtocolException In case of an http protocol error.
7045    */
7046   @Override /* Overridden from HttpClient */
7047   public <T> T execute(HttpUriRequest request, ResponseHandler<? extends T> responseHandler, HttpContext context) throws IOException {
7048      return httpClient.execute(request, responseHandler, context);
7049   }
7050
7051   /**
7052    * Same as {@link #formPost(Object, Object)} but doesn't specify the input yet.
7053    *
7054    * @param uri
7055    *    The URI of the remote REST resource.
7056    *    <br>Can be any of the following types:
7057    *    <ul>
7058    *       <li>{@link URIBuilder}
7059    *       <li>{@link URI}
7060    *       <li>{@link URL}
7061    *       <li>{@link String}
7062    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7063    *    </ul>
7064    * @return
7065    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
7066    *    as a parsed object.
7067    * @throws RestCallException If any authentication errors occurred.
7068    */
7069   public RestRequest formPost(Object uri) throws RestCallException {
7070      return request(op("POST", uri, NO_BODY));
7071   }
7072
7073   /**
7074    * Perform a <c>POST</c> request with a content type of <c>application/x-www-form-urlencoded</c>
7075    * against the specified URI.
7076    *
7077    * @param uri
7078    *    The URI of the remote REST resource.
7079    *    <br>Can be any of the following types:
7080    *    <ul>
7081    *       <li>{@link URIBuilder}
7082    *       <li>{@link URI}
7083    *       <li>{@link URL}
7084    *       <li>{@link String}
7085    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7086    *    </ul>
7087    * @param body
7088    *    The object to serialize and transmit to the URI as the body of the request.
7089    *    <ul class='spaced-list'>
7090    *       <li>{@link NameValuePair} - URL-encoded as a single name-value pair.
7091    *       <li>{@link NameValuePair} array - URL-encoded as name value pairs.
7092    *       <li>{@link PartList} - URL-encoded as name value pairs.
7093    *       <li>{@link Reader}/{@link InputStream}- Streamed directly and <l>Content-Type</l> set to <js>"application/x-www-form-urlencoded"</js>
7094    *       <li>{@link HttpResource} - Raw contents will be serialized to remote resource.  Additional headers and media type will be set on request.
7095    *       <li>{@link HttpEntity} - Bypass Juneau serialization and pass HttpEntity directly to HttpClient.
7096    *       <li>{@link Object} - Converted to a {@link SerializedEntity} using {@link UrlEncodingSerializer} to serialize.
7097    *       <li>{@link Supplier} - A supplier of anything on this list.
7098    *    </ul>
7099    * @return
7100    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
7101    *    as a parsed object.
7102    * @throws RestCallException If any authentication errors occurred.
7103    */
7104   public RestRequest formPost(Object uri, Object body) throws RestCallException {
7105      var req = request(op("POST", uri, NO_BODY));
7106      try {
7107         if (body instanceof Supplier<?> body2)
7108            body = body2.get();
7109         if (body instanceof NameValuePair body2)
7110            return req.content(new UrlEncodedFormEntity(l(body2)));
7111         if (body instanceof NameValuePair[] namevaluepairArray)
7112            return req.content(new UrlEncodedFormEntity(l(namevaluepairArray)));
7113         if (body instanceof PartList body2)
7114            return req.content(new UrlEncodedFormEntity(body2));
7115         if (body instanceof HttpResource body2)
7116            body2.getHeaders().forEach(req::header);
7117         if (body instanceof HttpEntity body2) {
7118            if (body2.getContentType() == null)
7119               req.header(ContentType.APPLICATION_FORM_URLENCODED);
7120            return req.content(body2);
7121         }
7122         if (body instanceof Reader || body instanceof InputStream)
7123            return req.header(ContentType.APPLICATION_FORM_URLENCODED).content(body);
7124         return req.content(serializedEntity(body, urlEncodingSerializer, null));
7125      } catch (IOException e) {
7126         throw new RestCallException(null, e, "Could not read form post body.");
7127      }
7128   }
7129
7130   /**
7131    * Perform a <c>POST</c> request with a content type of <c>application/x-www-form-urlencoded</c>
7132    * against the specified URI.
7133    *
7134    * @param uri
7135    *    The URI of the remote REST resource.
7136    *    <br>Can be any of the following types:
7137    *    <ul>
7138    *       <li>{@link URIBuilder}
7139    *       <li>{@link URI}
7140    *       <li>{@link URL}
7141    *       <li>{@link String}
7142    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7143    *    </ul>
7144    * @param parameters
7145    *    The parameters of the form post.
7146    *    <br>The parameters represent name/value pairs and must be an even number of arguments.
7147    *    <br>Parameters are converted to {@link BasicPart} objects.
7148    * @return
7149    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
7150    *    as a parsed object.
7151    * @throws RestCallException If any authentication errors occurred.
7152    */
7153   public RestRequest formPostPairs(Object uri, String...parameters) throws RestCallException {
7154      return formPost(uri, partList(parameters));
7155   }
7156
7157   /**
7158    * Perform a <c>GET</c> request against the root URI.
7159    *
7160    * @return
7161    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
7162    *    as a parsed object.
7163    * @throws RestCallException If any authentication errors occurred.
7164    */
7165   public RestRequest get() throws RestCallException {
7166      return request(op("GET", null, NO_BODY));
7167   }
7168
7169   /**
7170    * Perform a <c>GET</c> request against the specified URI.
7171    *
7172    * @param uri
7173    *    The URI of the remote REST resource.
7174    *    <br>Can be any of the following types:
7175    *    <ul>
7176    *       <li>{@link URIBuilder}
7177    *       <li>{@link URI}
7178    *       <li>{@link URL}
7179    *       <li>{@link String}
7180    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7181    *    </ul>
7182    * @return
7183    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
7184    *    as a parsed object.
7185    * @throws RestCallException If any authentication errors occurred.
7186    */
7187   public RestRequest get(Object uri) throws RestCallException {
7188      return request(op("GET", uri, NO_BODY));
7189   }
7190
7191   /**
7192    * Obtains the connection manager used by this client.
7193    *
7194    * @return The connection manager.
7195    * @deprecated Use {@link HttpClientBuilder}.
7196    */
7197   @Deprecated(since = "10.0", forRemoval = true)
7198   @Override /* Overridden from HttpClient */
7199   public ClientConnectionManager getConnectionManager() { return httpClient.getConnectionManager(); }
7200
7201   /**
7202    * Returns the connection manager if one was specified in the client builder.
7203    *
7204    * @return The connection manager.  May be <jk>null</jk>.
7205    */
7206   public HttpClientConnectionManager getHttpClientConnectionManager() { return connectionManager; }
7207
7208   /**
7209    * Obtains the parameters for this client.
7210    *
7211    * These parameters will become defaults for all requests being executed with this client, and for the parameters of dependent objects in this client.
7212    *
7213    * @return The default parameters.
7214    * @deprecated Use {@link RequestConfig}.
7215    */
7216   @Deprecated(since = "10.0", forRemoval = true)
7217   @Override /* Overridden from HttpClient */
7218   public HttpParams getParams() { return httpClient.getParams(); }
7219
7220   /**
7221    * Create a new proxy interface against a 3rd-party REST interface.
7222    *
7223    * <p>
7224    * The URI to the REST interface is based on the following values:
7225    * <ul>
7226    *    <li>The {@link Remote#path() @Remote(path)} annotation on the interface (<c>remote-path</c>).
7227    *    <li>The {@link Builder#rootUrl(Object) rootUrl} on the client (<c>root-url</c>).
7228    *    <li>The fully-qualified class name of the interface (<c>class-name</c>).
7229    * </ul>
7230    *
7231    * <p>
7232    * The URI calculation is as follows:
7233    * <ul>
7234    *    <li><c>remote-path</c> - If remote path is absolute.
7235    *    <li><c>root-uri/remote-path</c> - If remote path is relative and root-uri has been specified.
7236    *    <li><c>root-uri/class-name</c> - If remote path is not specified.
7237    * </ul>
7238    *
7239    * <p>
7240    * If the information is not available to resolve to an absolute URI, a {@link RemoteMetadataException} is thrown.
7241    *
7242    * <h5 class='section'>Examples:</h5>
7243    * <p class='bjava'>
7244    *    <jk>package</jk> org.apache.foo;
7245    *
7246    *    <ja>@RemoteResource</ja>(path=<js>"http://hostname/resturi/myinterface1"</js>)
7247    *    <jk>public interface</jk> MyInterface1 { ... }
7248    *
7249    *    <ja>@RemoteResource</ja>(path=<js>"/myinterface2"</js>)
7250    *    <jk>public interface</jk> MyInterface2 { ... }
7251    *
7252    *    <jk>public interface</jk> MyInterface3 { ... }
7253    *
7254    *    <jc>// Resolves to "http://localhost/resturi/myinterface1"</jc>
7255    *    MyInterface1 <jv>interface1</jv> = RestClient
7256    *       .<jsm>create</jsm>()
7257    *       .build()
7258    *       .getRemote(MyInterface1.<jk>class</jk>);
7259    *
7260    *    <jc>// Resolves to "http://hostname/resturi/myinterface2"</jc>
7261    *    MyInterface2 <jv>interface2</jv> = RestClient
7262    *       .<jsm>create</jsm>()
7263    *       .rootUrl(<js>"http://hostname/resturi"</js>)
7264    *       .build()
7265    *       .getRemote(MyInterface2.<jk>class</jk>);
7266    *
7267    *    <jc>// Resolves to "http://hostname/resturi/org.apache.foo.MyInterface3"</jc>
7268    *    MyInterface3 <jv>interface3</jv> = RestClient
7269    *       .<jsm>create</jsm>()
7270    *       .rootUrl(<js>"http://hostname/resturi"</js>)
7271    *       .build()
7272    *       .getRemote(MyInterface3.<jk>class</jk>);
7273    * </p>
7274    *
7275    * <h5 class='section'>Notes:</h5><ul>
7276    *    <li class='note'>
7277    *       If you plan on using your proxy in a multi-threaded environment, you'll want to use an underlying
7278    *       pooling client connection manager.
7279    * </ul>
7280    *
7281    * <h5 class='section'>See Also:</h5><ul>
7282    *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestProxies">REST Proxies</a>
7283    * </ul>
7284    *
7285    * @param <T> The interface to create a proxy for.
7286    * @param interfaceClass The interface to create a proxy for.
7287    *    <br>Cannot be <jk>null</jk>.
7288    * @return The new proxy interface.
7289    * @throws RemoteMetadataException If the REST URI cannot be determined based on the information given.
7290    */
7291   public <T> T getRemote(Class<T> interfaceClass) {
7292      return getRemote(interfaceClass, null);
7293   }
7294
7295   /**
7296    * Same as {@link #getRemote(Class)} except explicitly specifies the URI of the REST interface.
7297    *
7298    * <h5 class='section'>See Also:</h5><ul>
7299    *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestProxies">REST Proxies</a>
7300    * </ul>
7301    *
7302    * @param <T> The interface to create a proxy for.
7303    * @param interfaceClass The interface to create a proxy for.
7304    *    <br>Cannot be <jk>null</jk>.
7305    * @param rootUrl The URI of the REST interface.
7306    *    <br>Can be <jk>null</jk> (will use the root URL from the client builder if set).
7307    * @return The new proxy interface.
7308    */
7309   public <T> T getRemote(Class<T> interfaceClass, Object rootUrl) {
7310      return getRemote(interfaceClass, rootUrl, null, null);
7311   }
7312
7313   /**
7314    * Same as {@link #getRemote(Class, Object)} but allows you to override the serializer and parser used.
7315    *
7316    * <h5 class='section'>See Also:</h5><ul>
7317    *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestProxies">REST Proxies</a>
7318    * </ul>
7319
7320    * @param <T> The interface to create a proxy for.
7321    * @param interfaceClass The interface to create a proxy for.
7322    *    <br>Cannot be <jk>null</jk>.
7323    * @param rootUrl The URI of the REST interface.
7324    *    <br>Can be <jk>null</jk> (will use the root URL from the client builder if set).
7325    * @param serializer The serializer used to serialize POJOs to the body of the HTTP request.
7326    *    <br>Can be <jk>null</jk> (will use the default serializer from the client).
7327    * @param parser The parser used to parse POJOs from the body of the HTTP response.
7328    *    <br>Can be <jk>null</jk> (will use the default parser from the client).
7329    * @return The new proxy interface.
7330    */
7331   @SuppressWarnings({
7332      "java:S6541" // Brain method acceptable - remote proxy creation requires complex initialization logic
7333   })
7334   public <T> T getRemote(Class<T> interfaceClass, Object rootUrl, Serializer serializer, Parser parser) {
7335
7336      reqnn("interfaceClass", interfaceClass);
7337
7338      if (rootUrl == null)
7339         rootUrl = this.rootUrl != null ? this.rootUrl.get() : null;
7340
7341      final String restUrl2 = trimSlashes(emptyIfNull(rootUrl));
7342
7343      return (T)Proxy.newProxyInstance(interfaceClass.getClassLoader(), a(interfaceClass), new InvocationHandler() {
7344
7345         final RemoteMeta rm = new RemoteMeta(interfaceClass);
7346
7347         @Override /* Overridden from InvocationHandler */
7348      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
7349            var rom = rm.getOperationMeta(method);
7350
7351            // Resolve the effective request URL (interface/method baseUrl + @Url overrides, with the SSRF guard).
7352            var uri = resolveRemoteUri(interfaceClass, restUrl2, method, rom, rm, args);
7353
7354            var ror = rom.getReturns();
7355            if (ror.isFuture()) {
7356               return getExecutorService().submit(() -> {
7357                  try {
7358                     return executeRemoteWithRetry(uri, serializer, parser, method, rom, rm, args);
7359                  } catch (Exception e) {
7360                     throw toRex(e);
7361                  }
7362               });
7363            } else if (ror.isCompletableFuture()) {
7364               var cf = new CompletableFuture<>();
7365               getExecutorService().submit(() -> {
7366                  try {
7367                     cf.complete(executeRemoteWithRetry(uri, serializer, parser, method, rom, rm, args));
7368                  } catch (Exception e) {
7369                     cf.completeExceptionally(e);
7370                  }
7371                  return null;
7372               });
7373               return cf;
7374            }
7375
7376            try {
7377               return executeRemoteWithRetry(uri, serializer, parser, method, rom, rm, args);
7378            } catch (Exception e) {
7379               // Check if this is a RuntimeException wrapping a RestCallException with an Error cause
7380               if (e instanceof RuntimeException e2 && e2.getCause() instanceof RestCallException rce) {
7381                  var t = rce.getCause();
7382                  if (nn(t)) {
7383                     // Check if the cause matches the method's declared exception types
7384                     for (var t2 : method.getExceptionTypes())
7385                        if (t2.isInstance(t))
7386                           throw t; // Rethrow the original Throwable (can be Error)
7387                  }
7388               }
7389               throw e;
7390            }
7391         }
7392      });
7393   }
7394
7395   /**
7396    * Create a new proxy interface against an RRPC-style service.
7397    *
7398    * <p>
7399    * Remote interfaces are interfaces exposed on the server side using either the <c>RrpcServlet</c>
7400    * or <c>RRPC</c> REST methods.
7401    *
7402    * <p>
7403    * The URI to the REST interface is based on the following values:
7404    * <ul>
7405    *    <li>The {@link Remote#path() @Remote(path)} annotation on the interface (<c>remote-path</c>).
7406    *    <li>The {@link Builder#rootUrl(Object) rootUrl} on the client (<c>root-url</c>).
7407    *    <li>The fully-qualified class name of the interface (<c>class-name</c>).
7408    * </ul>
7409    *
7410    * <p>
7411    * The URI calculation is as follows:
7412    * <ul>
7413    *    <li><c>remote-path</c> - If remote path is absolute.
7414    *    <li><c>root-url/remote-path</c> - If remote path is relative and root-url has been specified.
7415    *    <li><c>root-url/class-name</c> - If remote path is not specified.
7416    * </ul>
7417    *
7418    * <p>
7419    * If the information is not available to resolve to an absolute URI, a {@link RemoteMetadataException} is thrown.
7420    *
7421    * <h5 class='section'>Notes:</h5><ul>
7422    *    <li class='note'>
7423    *       If you plan on using your proxy in a multi-threaded environment, you'll want to use an underlying
7424    *       pooling client connection manager.
7425    * </ul>
7426    *
7427    * <h5 class='section'>See Also:</h5><ul>
7428    *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestRpc">REST/RPC</a>
7429    * </ul>
7430    *
7431    * @param <T> The interface to create a proxy for.
7432    * @param interfaceClass The interface to create a proxy for.
7433    *    <br>Cannot be <jk>null</jk>.
7434    * @return The new proxy interface.
7435    * @throws RemoteMetadataException If the REST URI cannot be determined based on the information given.
7436    */
7437   public <T> T getRrpcInterface(Class<T> interfaceClass) {
7438      return getRrpcInterface(interfaceClass, null);
7439   }
7440
7441   /**
7442    * Same as {@link #getRrpcInterface(Class)} except explicitly specifies the URI of the REST interface.
7443    *
7444    * <h5 class='section'>See Also:</h5><ul>
7445    *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestRpc">REST/RPC</a>
7446    * </ul>
7447    *
7448    * @param <T> The interface to create a proxy for.
7449    * @param interfaceClass The interface to create a proxy for.
7450    *    <br>Cannot be <jk>null</jk>.
7451    * @param uri The URI of the REST interface.
7452    *    <br>Can be <jk>null</jk> (will use the root URL from the client builder if set).
7453    * @return The new proxy interface.
7454    */
7455   public <T> T getRrpcInterface(Class<T> interfaceClass, Object uri) {
7456      return getRrpcInterface(interfaceClass, uri, null, null);
7457   }
7458
7459   /**
7460    * Same as {@link #getRrpcInterface(Class, Object)} but allows you to override the serializer and parser used.
7461    *
7462    * <h5 class='section'>See Also:</h5><ul>
7463    *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestRpc">REST/RPC</a>
7464    * </ul>
7465    *
7466    * @param <T> The interface to create a proxy for.
7467    * @param interfaceClass The interface to create a proxy for.
7468    *    <br>Cannot be <jk>null</jk>.
7469    * @param uri The URI of the REST interface.
7470    *    <br>Can be <jk>null</jk> (will use the root URL from the client builder if set).
7471    * @param serializer The serializer used to serialize POJOs to the body of the HTTP request.
7472    *    <br>Can be <jk>null</jk> (will use the default serializer from the client).
7473    * @param parser The parser used to parse POJOs from the body of the HTTP response.
7474    *    <br>Can be <jk>null</jk> (will use the default parser from the client).
7475    * @return The new proxy interface.
7476    */
7477   public <T> T getRrpcInterface(Class<T> interfaceClass, Object uri, Serializer serializer, Parser parser) {
7478
7479      if (uri == null) {
7480         var rm = new RrpcInterfaceMeta(interfaceClass, "");
7481         var path = rm.getPath();
7482         if (path.indexOf("://") == -1) {
7483            var rootUrlValue = rootUrl != null ? rootUrl.get() : null;
7484            if (isEmpty(rootUrlValue))
7485               throw new RemoteMetadataException(interfaceClass, "Root URI has not been specified.  Cannot construct absolute path to remote interface.");
7486            path = trimSlashes(rootUrlValue) + '/' + path;
7487         }
7488         uri = path;
7489      }
7490
7491      final String restUrl2 = s(uri);
7492
7493      return (T)Proxy.newProxyInstance(interfaceClass.getClassLoader(), a(interfaceClass), new InvocationHandler() {
7494
7495         final RrpcInterfaceMeta rm = new RrpcInterfaceMeta(interfaceClass, restUrl2);
7496
7497         @Override /* Overridden from InvocationHandler */
7498         public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
7499            var rim = rm.getMethodMeta(method);
7500
7501            var uri = rim.getUri();
7502            RestResponse res;
7503
7504            try {
7505               // @formatter:off
7506               RestRequest rc = request("POST", uri, true)
7507                  .serializer(serializer)
7508                  .content(args)
7509                  .rethrow(RuntimeException.class)
7510                  .rethrow(method.getExceptionTypes());
7511               // @formatter:on
7512
7513               res = rc.run();
7514
7515               var v = res.getContent().as(method.getGenericReturnType());
7516               if (v == null && method.getReturnType().isPrimitive())
7517                  v = ClassInfo.of(method.getReturnType()).getPrimitiveDefault();
7518               return v;
7519
7520            } catch (Exception e) {
7521               // Check if this is a RuntimeException wrapping a RestCallException with an Error cause
7522               if (e instanceof RuntimeException e2 && e2.getCause() instanceof RestCallException rce) {
7523                  var t = rce.getCause();
7524                  if (nn(t)) {
7525                     // Check if the cause matches the method's declared exception types
7526                     for (var t2 : method.getExceptionTypes())
7527                        if (t2.isInstance(t))
7528                           throw t; // Rethrow the original Throwable (can be Error)
7529                  }
7530               }
7531               if (e instanceof RestCallException e2) {
7532                  var t = e2.getCause();
7533                  if (nn(t)) {
7534                     // Check if the cause matches the method's declared exception types
7535                     for (var t2 : method.getExceptionTypes())
7536                        if (t2.isInstance(t))
7537                           throw t; // Rethrow the original Throwable (can be Error)
7538                     if (t instanceof Exception t2)
7539                        e = t2;
7540                  }
7541               }
7542               if (e instanceof RuntimeException e2)
7543                  throw e2;
7544               for (var t2 : method.getExceptionTypes())
7545                  if (t2.isInstance(e))
7546                     throw e;
7547               throw toRex(e);
7548            }
7549         }
7550      });
7551   }
7552
7553   /**
7554    * Perform a <c>HEAD</c> request against the specified URI.
7555    *
7556    * @param uri
7557    *    The URI of the remote REST resource.
7558    *    <br>Can be any of the following types:
7559    *    <ul>
7560    *       <li>{@link URIBuilder}
7561    *       <li>{@link URI}
7562    *       <li>{@link URL}
7563    *       <li>{@link String}
7564    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7565    *    </ul>
7566    * @return
7567    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
7568    *    as a parsed object.
7569    * @throws RestCallException If any authentication errors occurred.
7570    */
7571   public RestRequest head(Object uri) throws RestCallException {
7572      return request(op("HEAD", uri, NO_BODY));
7573   }
7574
7575   /**
7576    * Perform an <c>OPTIONS</c> request against the specified URI.
7577    *
7578    * @param uri
7579    *    The URI of the remote REST resource.
7580    *    <br>Can be any of the following types:
7581    *    <ul>
7582    *       <li>{@link URIBuilder}
7583    *       <li>{@link URI}
7584    *       <li>{@link URL}
7585    *       <li>{@link String}
7586    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7587    *    </ul>
7588    * @return
7589    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
7590    *    as a parsed object.
7591    * @throws RestCallException If any authentication errors occurred.
7592    */
7593   public RestRequest options(Object uri) throws RestCallException {
7594      return request(op("OPTIONS", uri, NO_BODY));
7595   }
7596
7597   /**
7598    * Same as {@link #patch(Object, Object)} but don't specify the input yet.
7599    *
7600    * <p>
7601    * You must call {@link RestRequest#content(Object)} to set the contents on the result object.
7602    *
7603    * @param uri
7604    *    The URI of the remote REST resource.
7605    *    <br>Can be any of the following types:
7606    *    <ul>
7607    *       <li>{@link URIBuilder}
7608    *       <li>{@link URI}
7609    *       <li>{@link URL}
7610    *       <li>{@link String}
7611    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7612    *    </ul>
7613    * @return
7614    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
7615    *    as a parsed object.
7616    * @throws RestCallException REST call failed.
7617    */
7618   public RestRequest patch(Object uri) throws RestCallException {
7619      return request(op(PATCH, uri, NO_BODY));
7620   }
7621
7622   /**
7623    * Perform a <c>PATCH</c> request against the specified URI.
7624    *
7625    * @param uri
7626    *    The URI of the remote REST resource.
7627    *    <br>Can be any of the following types:
7628    *    <ul>
7629    *       <li>{@link URIBuilder}
7630    *       <li>{@link URI}
7631    *       <li>{@link URL}
7632    *       <li>{@link String}
7633    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7634    *    </ul>
7635    * @param body
7636    *    The object to serialize and transmit to the URI as the body of the request.
7637    *    Can be of the following types:
7638    *    <ul class='spaced-list'>
7639    *       <li>
7640    *          {@link Reader} - Raw contents of {@code Reader} will be serialized to remote resource.
7641    *       <li>
7642    *          {@link InputStream} - Raw contents of {@code InputStream} will be serialized to remote resource.
7643    *       <li>
7644    *          {@link HttpResource} - Raw contents will be serialized to remote resource.  Additional headers and media type will be set on request.
7645    *       <li>
7646    *          {@link HttpEntity} - Bypass Juneau serialization and pass HttpEntity directly to HttpClient.
7647    *       <li>
7648    *          {@link Object} - POJO to be converted to text using the {@link Serializer} registered with the
7649    *          {@link RestClient}.
7650    *       <li>
7651    *          {@link PartList} - Converted to a URL-encoded FORM post.
7652    *       <li>
7653    *          {@link Supplier} - A supplier of anything on this list.
7654    *    </ul>
7655    * @return
7656    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
7657    *    as a parsed object.
7658    * @throws RestCallException If any authentication errors occurred.
7659    */
7660   public RestRequest patch(Object uri, Object body) throws RestCallException {
7661      return request(op(PATCH, uri, body));
7662   }
7663
7664   /**
7665    * Perform a <c>PATCH</c> request against the specified URI as a plain text body bypassing the serializer.
7666    *
7667    * @param uri
7668    *    The URI of the remote REST resource.
7669    *    <br>Can be any of the following types:
7670    *    <ul>
7671    *       <li>{@link URIBuilder}
7672    *       <li>{@link URI}
7673    *       <li>{@link URL}
7674    *       <li>{@link String}
7675    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7676    *    </ul>
7677    * @param body
7678    *    The object to serialize and transmit to the URI as the body of the request bypassing the serializer.
7679    * @param contentType
7680    *    The content type of the request.
7681    * @return
7682    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
7683    *    as a parsed object.
7684    * @throws RestCallException If any authentication errors occurred.
7685    */
7686   public RestRequest patch(Object uri, String body, ContentType contentType) throws RestCallException {
7687      return request(op(PATCH, uri, stringBody(body))).header(contentType);
7688   }
7689
7690   /**
7691    * Same as {@link #post(Object, Object)} but don't specify the input yet.
7692    *
7693    * <p>
7694    * You must call either {@link RestRequest#content(Object)} or {@link RestRequest#formData(String, Object)} to set the
7695    * contents on the result object.
7696    *
7697    * <h5 class='section'>Notes:</h5><ul>
7698    *    <li class='note'>Use {@link #formPost(Object, Object)} for <c>application/x-www-form-urlencoded</c> form posts.
7699    * </ul>
7700    *
7701    * @param uri
7702    *    The URI of the remote REST resource.
7703    *    <br>Can be any of the following types:
7704    *    <ul>
7705    *       <li>{@link URIBuilder}
7706    *       <li>{@link URI}
7707    *       <li>{@link URL}
7708    *       <li>{@link String}
7709    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7710    *    </ul>
7711    * @return
7712    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
7713    *    as a parsed object.
7714    * @throws RestCallException REST call failed.
7715    */
7716   public RestRequest post(Object uri) throws RestCallException {
7717      return request(op("POST", uri, NO_BODY));
7718   }
7719
7720   /**
7721    * Perform a <c>POST</c> request against the specified URI.
7722    *
7723    * <h5 class='section'>Notes:</h5><ul>
7724    *    <li class='note'>Use {@link #formPost(Object, Object)} for <c>application/x-www-form-urlencoded</c> form posts.
7725    * </ul>
7726    *
7727    * @param uri
7728    *    The URI of the remote REST resource.
7729    *    <br>Can be any of the following types:
7730    *    <ul>
7731    *       <li>{@link URIBuilder}
7732    *       <li>{@link URI}
7733    *       <li>{@link URL}
7734    *       <li>{@link String}
7735    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7736    *    </ul>
7737    * @param body
7738    *    The object to serialize and transmit to the URI as the body of the request.
7739    *    Can be of the following types:
7740    *    <ul class='spaced-list'>
7741    *       <li>
7742    *          {@link Reader} - Raw contents of {@code Reader} will be serialized to remote resource.
7743    *       <li>
7744    *          {@link InputStream} - Raw contents of {@code InputStream} will be serialized to remote resource.
7745    *       <li>
7746    *          {@link Object} - POJO to be converted to text using the {@link Serializer} registered with the
7747    *          {@link RestClient}.
7748    *       <li>
7749    *          {@link HttpEntity} / {@link HttpResource} - Bypass Juneau serialization and pass HttpEntity directly to HttpClient.
7750    *       <li>
7751    *          {@link PartList} - Converted to a URL-encoded FORM post.
7752    *       <li>
7753    *          {@link Supplier} - A supplier of anything on this list.
7754    *    </ul>
7755    * @return
7756    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
7757    *    as a parsed object.
7758    * @throws RestCallException If any authentication errors occurred.
7759    */
7760   public RestRequest post(Object uri, Object body) throws RestCallException {
7761      return request(op("POST", uri, body));
7762   }
7763
7764   /**
7765    * Perform a <c>POST</c> request against the specified URI as a plain text body bypassing the serializer.
7766    *
7767    * @param uri
7768    *    The URI of the remote REST resource.
7769    *    <br>Can be any of the following types:
7770    *    <ul>
7771    *       <li>{@link URIBuilder}
7772    *       <li>{@link URI}
7773    *       <li>{@link URL}
7774    *       <li>{@link String}
7775    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7776    *    </ul>
7777    * @param body
7778    *    The object to serialize and transmit to the URI as the body of the request bypassing the serializer.
7779    * @param contentType
7780    *    The content type of the request.
7781    * @return
7782    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
7783    *    as a parsed object.
7784    * @throws RestCallException If any authentication errors occurred.
7785    */
7786   public RestRequest post(Object uri, String body, ContentType contentType) throws RestCallException {
7787      return request(op("POST", uri, stringBody(body))).header(contentType);
7788   }
7789
7790   /**
7791    * Same as {@link #put(Object, Object)} but don't specify the input yet.
7792    *
7793    * <p>
7794    * You must call either {@link RestRequest#content(Object)} or {@link RestRequest#formData(String, Object)}
7795    * to set the contents on the result object.
7796    *
7797    * @param uri
7798    *    The URI of the remote REST resource.
7799    *    <br>Can be any of the following types:
7800    *    <ul>
7801    *       <li>{@link URIBuilder}
7802    *       <li>{@link URI}
7803    *       <li>{@link URL}
7804    *       <li>{@link String}
7805    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7806    *    </ul>
7807    * @return
7808    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
7809    *    as a parsed object.
7810    * @throws RestCallException REST call failed.
7811    */
7812   public RestRequest put(Object uri) throws RestCallException {
7813      return request(op("PUT", uri, NO_BODY));
7814   }
7815
7816   /**
7817    * Perform a <c>PUT</c> request against the specified URI.
7818    *
7819    * @param uri
7820    *    The URI of the remote REST resource.
7821    *    <br>Can be any of the following types:
7822    *    <ul>
7823    *       <li>{@link URIBuilder}
7824    *       <li>{@link URI}
7825    *       <li>{@link URL}
7826    *       <li>{@link String}
7827    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7828    *    </ul>
7829    * @param body
7830    *    The object to serialize and transmit to the URI as the body of the request.
7831    *    Can be of the following types:
7832    *    <ul class='spaced-list'>
7833    *       <li>
7834    *          {@link Reader} - Raw contents of {@code Reader} will be serialized to remote resource.
7835    *       <li>
7836    *          {@link InputStream} - Raw contents of {@code InputStream} will be serialized to remote resource.
7837    *       <li>
7838    *          {@link Object} - POJO to be converted to text using the {@link Serializer} registered with the
7839    *          {@link RestClient}.
7840    *       <li>
7841    *          {@link HttpEntity} / {@link HttpResource} - Bypass Juneau serialization and pass HttpEntity directly to HttpClient.
7842    *       <li>
7843    *          {@link PartList} - Converted to a URL-encoded FORM post.
7844    *       <li>
7845    *          {@link Supplier} - A supplier of anything on this list.
7846    *    </ul>
7847    * @return
7848    *    A {@link RestRequest} object that can be further tailored before executing the request
7849    *    and getting the response as a parsed object.
7850    * @throws RestCallException If any authentication errors occurred.
7851    */
7852   public RestRequest put(Object uri, Object body) throws RestCallException {
7853      return request(op("PUT", uri, body));
7854   }
7855
7856   /**
7857    * Perform a <c>PUT</c> request against the specified URI using a plain text body bypassing the serializer.
7858    *
7859    * @param uri
7860    *    The URI of the remote REST resource.
7861    *    <br>Can be any of the following types:
7862    *    <ul>
7863    *       <li>{@link URIBuilder}
7864    *       <li>{@link URI}
7865    *       <li>{@link URL}
7866    *       <li>{@link String}
7867    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7868    *    </ul>
7869    * @param body
7870    *    The object to serialize and transmit to the URI as the body of the request bypassing the serializer.
7871    * @param contentType The content type of the request.
7872    * @return
7873    *    A {@link RestRequest} object that can be further tailored before executing the request
7874    *    and getting the response as a parsed object.
7875    * @throws RestCallException If any authentication errors occurred.
7876    */
7877   public RestRequest put(Object uri, String body, ContentType contentType) throws RestCallException {
7878      return request(op("PUT", uri, stringBody(body))).header(contentType);
7879   }
7880
7881   /**
7882    * Perform a generic REST call.
7883    *
7884    * @param method The HTTP method.
7885    *    <br>Cannot be <jk>null</jk>.
7886    * @param uri
7887    *    The URI of the remote REST resource.
7888    *    <br>Can be any of the following types:
7889    *    <ul>
7890    *       <li>{@link URIBuilder}
7891    *       <li>{@link URI}
7892    *       <li>{@link URL}
7893    *       <li>{@link String}
7894    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7895    *    </ul>
7896    *    <br>Can be <jk>null</jk> (will result in an invalid request).
7897    * @return
7898    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
7899    *    as a parsed object.
7900    * @throws RestCallException If any authentication errors occurred.
7901    */
7902   public RestRequest request(String method, Object uri) throws RestCallException {
7903      return request(op(method, uri, NO_BODY));
7904   }
7905
7906   /**
7907    * Perform a generic REST call.
7908    *
7909    * <p>
7910    * Typically you're going to use {@link #request(String, Object)} or {@link #request(String, Object, Object)},
7911    * but this method is provided to allow you to perform non-standard HTTP methods (e.g. HTTP FOO).
7912    *
7913    * @param method The method name (e.g. <js>"GET"</js>, <js>"OPTIONS"</js>).
7914    *    <br>Cannot be <jk>null</jk>.
7915    * @param uri
7916    *    The URI of the remote REST resource.
7917    *    <br>Can be any of the following types:
7918    *    <ul>
7919    *       <li>{@link URIBuilder}
7920    *       <li>{@link URI}
7921    *       <li>{@link URL}
7922    *       <li>{@link String}
7923    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7924    *    </ul>
7925    *    <br>Can be <jk>null</jk> (will result in an invalid request).
7926    * @param hasBody Boolean flag indicating if the specified request has content associated with it.
7927    * @return
7928    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
7929    *    as a parsed object.
7930    * @throws RestCallException If any authentication errors occurred.
7931    */
7932   public RestRequest request(String method, Object uri, boolean hasBody) throws RestCallException {
7933      return request(op(method, uri, NO_BODY).hasContent(hasBody));
7934   }
7935
7936   /**
7937    * Perform a generic REST call.
7938    *
7939    * @param method The HTTP method.
7940    *    <br>Cannot be <jk>null</jk>.
7941    * @param uri
7942    *    The URI of the remote REST resource.
7943    *    <br>Can be any of the following types:
7944    *    <ul>
7945    *       <li>{@link URIBuilder}
7946    *       <li>{@link URI}
7947    *       <li>{@link URL}
7948    *       <li>{@link String}
7949    *       <li>{@link Object} - Converted to <c>String</c> using <c>toString()</c>
7950    *    </ul>
7951    *    <br>Can be <jk>null</jk> (will result in an invalid request).
7952    * @param body
7953    *    The HTTP body content.
7954    *    Can be of the following types:
7955    *    <ul class='spaced-list'>
7956    *       <li>
7957    *          {@link Reader} - Raw contents of {@code Reader} will be serialized to remote resource.
7958    *       <li>
7959    *          {@link InputStream} - Raw contents of {@code InputStream} will be serialized to remote resource.
7960    *       <li>
7961    *          {@link HttpResource} - Raw contents will be serialized to remote resource.  Additional headers and media type will be set on request.
7962    *       <li>
7963    *          {@link HttpEntity} - Bypass Juneau serialization and pass HttpEntity directly to HttpClient.
7964    *       <li>
7965    *          {@link Object} - POJO to be converted to text using the {@link Serializer} registered with the
7966    *          {@link RestClient}.
7967    *       <li>
7968    *          {@link PartList} - Converted to a URL-encoded FORM post.
7969    *       <li>
7970    *          {@link Supplier} - A supplier of anything on this list.
7971    *    </ul>
7972    *    This parameter is IGNORED if the method type normally does not have content.
7973    * @return
7974    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
7975    *    as a parsed object.
7976    * @throws RestCallException If any authentication errors occurred.
7977    */
7978   public RestRequest request(String method, Object uri, Object body) throws RestCallException {
7979      return request(op(method, uri, body));
7980   }
7981
7982   private static RestOperation op(String method, Object url, Object body) {
7983      return RestOperation.of(method, url, body);
7984   }
7985
7986   private static Reader stringBody(String body) {
7987      return body == null ? null : new StringReader(s(body));
7988   }
7989
7990   /**
7991    * Creates a {@link RestRequest} object from the specified {@link HttpRequest} object.
7992    *
7993    * <p>
7994    * Subclasses can override this method to provide their own specialized {@link RestRequest} objects.
7995    *
7996    * <h5 class='section'>Notes:</h5><ul>
7997    *    <li class='warn'>The SSRF guard of {@code @Remote} calls travels on the request's {@link HttpContext}, which an
7998    *       override of {@link RestRequest#run()} in the returned request's class may drop (by copying the request, or
7999    *       sending it with another context), and depends on this client's connection manager, which a request bound to a different client does not use.  So an SSRF-guard-active
8000    *       {@code @Remote} call (one without the {@link Builder#allowPrivateUrls(boolean) allowPrivateUrls} opt-in) is
8001    *       refused through such a request, whether this method or {@link #request(String, Object, boolean)} returns it.
8002    *       Ordinary requests are unaffected.
8003    * </ul>
8004    *
8005    * @param uri The target.
8006    * @param method The HTTP method (uppercase).
8007    * @param hasBody Whether this method has a request entity.
8008    * @return A new {@link RestRequest} object.
8009    * @throws RestCallException If an exception or non-200 response code occurred during the connection attempt.
8010    */
8011   protected RestRequest createRequest(URI uri, String method, boolean hasBody) throws RestCallException {
8012      return new RestRequest(this, uri, method, hasBody);
8013   }
8014
8015   /**
8016    * Creates a {@link RestResponse} object from the specified {@link HttpResponse} object.
8017    *
8018    * <p>
8019    * Subclasses can override this method to provide their own specialized {@link RestResponse} objects.
8020    *
8021    * @param request The request creating this response.
8022    * @param httpResponse The response object to wrap.
8023    * @param parser The parser to use to parse the response.
8024    *
8025    * @return A new {@link RestResponse} object.
8026    * @throws RestCallException If an exception or non-200 response code occurred during the connection attempt.
8027    */
8028   protected RestResponse createResponse(RestRequest request, HttpResponse httpResponse, Parser parser) throws RestCallException {
8029      return new RestResponse(this, request, httpResponse, parser);
8030   }
8031
8032   /**
8033    * @deprecated Object.finalize() is deprecated. Use try-with-resources or explicit close() calls instead.
8034    */
8035   @Override
8036   @Deprecated(since = "9", forRemoval = true) // Object.finalize() is deprecated
8037   @SuppressWarnings({
8038      "java:S1113" // Kept for detectLeaks; logs warning when RestClient is GC'd without close
8039   })
8040   protected void finalize() throws Throwable {
8041      if (detectLeaks && ! isClosed.get() && ! keepHttpClientOpen) {
8042         var sb = new StringBuilder("WARNING:  RestClient garbage collected before it was finalized.");  // NOT DEBUG
8043         if (nn(creationStack)) {
8044            sb.append("\nCreation Stack:");  // NOT DEBUG
8045            for (var e : creationStack) {
8046               sb.append("\n\t").append(e);  // NOT DEBUG
8047            }
8048         }
8049         log(WARNING, sb.toString());
8050      }
8051   }
8052
8053   /**
8054    * Returns the part parser associated with this client.
8055    *
8056    * @return The part parser associated with this client.
8057    */
8058   protected HttpPartParser getPartParser() { return partParser; }
8059
8060   /**
8061    * Returns the part parser instance of the specified type.
8062    *
8063    * @param c The part parser class.
8064    * @return The part parser.
8065    */
8066   protected HttpPartParser getPartParser(Class<? extends HttpPartParser> c) {
8067      var x = partParsers.get(c);
8068      if (x == null) {
8069         try {
8070            x = BeanInstantiator.of(c, beanStore).run();
8071         } catch (ExecutableException e) {
8072            throw toRex(e);
8073         }
8074         partParsers.put(c, x);
8075      }
8076      return x;
8077   }
8078
8079   /**
8080    * Returns the part serializer associated with this client.
8081    *
8082    * @return The part serializer associated with this client.
8083    */
8084   protected HttpPartSerializer getPartSerializer() { return partSerializer; }
8085
8086   /**
8087    * Returns the part serializer instance of the specified type.
8088    *
8089    * @param c The part serializer class.
8090    * @return The part serializer.
8091    */
8092   protected HttpPartSerializer getPartSerializer(Class<? extends HttpPartSerializer> c) {
8093      var x = partSerializers.get(c);
8094      if (x == null) {
8095         try {
8096            x = BeanInstantiator.of(c, beanStore).run();
8097         } catch (ExecutableException e) {
8098            throw toRex(e);
8099         }
8100         partSerializers.put(c, x);
8101      }
8102      return x;
8103   }
8104
8105   /**
8106    * Gets called add the end of the constructor call to perform any post-initialization.
8107    */
8108   protected void init() {
8109      // No-op: Intentional empty implementation for optional override method
8110   }
8111
8112   /**
8113    * Returns <jk>true</jk> if empty request form-data parameter values should be ignored.
8114    *
8115    * @return <jk>true</jk> if empty request form-data parameter values should be ignored.
8116    */
8117   protected boolean isSkipEmptyFormData() { return skipEmptyFormData; }
8118
8119   /**
8120    * Returns <jk>true</jk> if empty request header values should be ignored.
8121    *
8122    * @return <jk>true</jk> if empty request header values should be ignored.
8123    */
8124   protected boolean isSkipEmptyHeaderData() { return skipEmptyHeaderData; }
8125
8126   /**
8127    * Returns <jk>true</jk> if empty request query parameter values should be ignored.
8128    *
8129    * @return <jk>true</jk> if empty request query parameter values should be ignored.
8130    */
8131   protected boolean isSkipEmptyQueryData() { return skipEmptyQueryData; }
8132
8133   /**
8134    * Logs a message.
8135    *
8136    * @param level The log level.
8137    * @param msg The message with {@link String#format(String, Object...) String.format}-style (<c>%s</c>) arguments.
8138    * @param args The arguments.
8139    */
8140   protected void log(Level level, String msg, Object...args) {
8141      if (logger.isLoggable(level)) {
8142         String formattedMsg = f(msg, args);
8143         logger.log(level, formattedMsg);
8144         if (logToConsole)
8145            console.println(formattedMsg);
8146      } else if (logToConsole) {
8147         console.println(f(msg, args));
8148      }
8149   }
8150
8151   /**
8152    * Logs a message.
8153    *
8154    * @param level The log level.
8155    * @param t Thrown exception.
8156    *    <br>Can be <jk>null</jk> (no exception stack trace will be logged).
8157    * @param msg The message.
8158    * @param args Optional message arguments.
8159    */
8160   protected void log(Level level, Throwable t, String msg, Object...args) {
8161      if (logger.isLoggable(level)) {
8162         String formattedMsg = f(msg, args);
8163         logger.log(level, formattedMsg, t);
8164         if (logToConsole) {
8165            console.println(f(msg, args));
8166            if (nn(t))
8167               t.printStackTrace(console);
8168         }
8169      } else if (logToConsole) {
8170         console.println(f(msg, args));
8171         if (nn(t))
8172            t.printStackTrace(console);
8173      }
8174   }
8175
8176   /**
8177    * Interceptor method called immediately after the RestRequest object is created and all headers/query/form-data has been set on the request from the client.
8178    *
8179    * <p>
8180    * Subclasses can override this method to handle any cleanup operations.
8181    *
8182    * <h5 class='section'>See Also:</h5><ul>
8183    *    <li class='jm'>{@link Builder#interceptors(Object...)}
8184    * </ul>
8185    *
8186    * @param req The HTTP request.
8187    * @param res The HTTP response.
8188    * @throws RestCallException If any of the interceptors threw an exception.
8189    */
8190   protected void onCallClose(RestRequest req, RestResponse res) throws RestCallException {
8191      try {
8192         for (var rci : interceptors)
8193            rci.onClose(req, res);
8194      } catch (RuntimeException | RestCallException e) {
8195         throw e;
8196      } catch (Exception e) {
8197         throw new RestCallException(res, e, "Interceptor threw an exception on close.");
8198      }
8199   }
8200
8201   /**
8202    * Interceptor method called immediately after an HTTP response has been received.
8203    *
8204    * <p>
8205    * Subclasses can override this method to intercept the response and perform special modifications.
8206    *
8207    * <h5 class='section'>See Also:</h5><ul>
8208    *    <li class='jm'>{@link Builder#interceptors(Object...)}
8209    * </ul>
8210    *
8211    * @param req The HTTP request.
8212    * @param res The HTTP response.
8213    * @throws RestCallException If any of the interceptors threw an exception.
8214    */
8215   protected void onCallConnect(RestRequest req, RestResponse res) throws RestCallException {
8216      try {
8217         for (var rci : interceptors)
8218            rci.onConnect(req, res);
8219      } catch (RuntimeException | RestCallException e) {
8220         throw e;
8221      } catch (Exception e) {
8222         throw new RestCallException(res, e, "Interceptor threw an exception on connect.");
8223      }
8224   }
8225
8226   /**
8227    * Interceptor method called immediately after the RestRequest object is created and all headers/query/form-data has been copied from the client.
8228    *
8229    * <p>
8230    * Subclasses can override this method to intercept the request and perform special modifications.
8231    *
8232    * <h5 class='section'>See Also:</h5><ul>
8233    *    <li class='jm'>{@link Builder#interceptors(Object...)}
8234    * </ul>
8235    *
8236    * @param req The HTTP request.
8237    * @throws RestCallException If any of the interceptors threw an exception.
8238    */
8239   protected void onCallInit(RestRequest req) throws RestCallException {
8240      try {
8241         for (var rci : interceptors)
8242            rci.onInit(req);
8243      } catch (RuntimeException | RestCallException e) {
8244         throw e;
8245      } catch (Exception e) {
8246         throw new RestCallException(null, e, "Interceptor threw an exception on init.");
8247      }
8248   }
8249
8250   @Override /* Overridden from MarshallingContextable */
8251   protected FluentMap<String,Object> properties() {
8252      return super.properties()
8253         .a("errorCodes", errorCodes)
8254         .a("executorService", executorService.get())
8255         .a("executorServiceShutdownOnClose", executorServiceShutdownOnClose)
8256         .a("headerData", headerData)
8257         .a("interceptors", interceptors)
8258         .a("keepHttpClientOpen", keepHttpClientOpen)
8259         .a("partParser", partParser)
8260         .a("partSerializer", partSerializer)
8261         .a("queryData", queryData)
8262         .a("rootUrl", rootUrl != null ? rootUrl.get() : null);
8263   }
8264
8265   /**
8266    * Perform an arbitrary request against the specified URI.
8267    *
8268    * <p>
8269    * All requests feed through this method so it can be used to intercept request creations and make modifications
8270    * (such as add headers).
8271    *
8272    * @param op The operation that identifies the HTTP method, URL, and optional payload.
8273    * @return
8274    *    A {@link RestRequest} object that can be further tailored before executing the request and getting the response
8275    *    as a parsed object.
8276    * @throws RestCallException If any authentication errors occurred.
8277    */
8278   protected RestRequest request(RestOperation op) throws RestCallException {
8279      if (isClosed.get()) {
8280         Exception e2 = null;
8281         if (nn(closedStack)) {
8282            e2 = new Exception("Creation stack:");
8283            e2.setStackTrace(closedStack);
8284            throw new RestCallException(null, e2, "RestClient.close() has already been called.  This client cannot be reused.");
8285         }
8286         throw new RestCallException(null, null,
8287            "RestClient.close() has already been called.  This client cannot be reused.  Closed location stack trace can be displayed by setting the system property 'org.apache.juneau.rest.client2.RestClient.trackCreation' to true.");
8288      }
8289
8290      var req = createRequest(toUri(op.getUri(), rootUrl != null ? rootUrl.get() : null), op.getMethod(), op.hasContent());
8291
8292      onCallInit(req);
8293
8294      req.content(op.getContent());
8295
8296      return req;
8297   }
8298
8299   /**
8300    * Entrypoint for executing all requests and returning a response.
8301    *
8302    * <p>
8303    * Subclasses can override this method to provide specialized handling.
8304    *
8305    * <p>
8306    * The behavior of this method can also be modified by specifying a different {@link RestCallHandler}.
8307    *
8308    * <h5 class='section'>Notes:</h5><ul>
8309    *    <li class='warn'>The SSRF guard of {@code @Remote} calls travels on the request's {@code HttpContext}, which this
8310    *       client cannot guarantee an override passes on unchanged.  So a client whose class overrides this method,
8311    *       {@link #execute(HttpHost, HttpRequest, HttpContext)} or {@link #execute(HttpUriRequest, HttpContext)} refuses every
8312    *       SSRF-guard-active {@code @Remote} call (one without the {@link Builder#allowPrivateUrls(boolean) allowPrivateUrls}
8313    *       opt-in).  Ordinary requests are unaffected.
8314    * </ul>
8315    *
8316    * <h5 class='section'>See Also:</h5><ul>
8317    *    <li class='jm'>{@link Builder#callHandler()}
8318    * </ul>
8319    *
8320    * @param target The target host for the request.
8321    *    <br>Implementations may accept <jk>null</jk> if they can still determine a route, for example to a default
8322    *       target or by inspecting the request.
8323    * @param request The request to execute.
8324    * @param context The context to use for the execution, or <jk>null</jk> to use the default context.
8325    * @return
8326    *    The response to the request.
8327    *    <br>This is always a final response, never an intermediate response with an 1xx status code.
8328    *    <br>Whether redirects or authentication challenges will be returned or handled automatically depends on the
8329    *       implementation and configuration of this client.
8330    * @throws IOException In case of a problem or the connection was aborted.
8331    * @throws ClientProtocolException In case of an http protocol error.
8332    */
8333   protected HttpResponse run(HttpHost target, HttpRequest request, HttpContext context) throws IOException {
8334      return callHandler.run(target, request, context);
8335   }
8336
8337   // The methods a request is dispatched through on its way from RestRequest to the HttpClient (run(...), then the two
8338   // execute(...) overloads BasicRestCallHandler calls).
8339   private static final List<Method> DISPATCH_METHODS = dispatchMethods();
8340
8341   private static List<Method> dispatchMethods() {
8342      try {
8343         return List.of(
8344            RestClient.class.getDeclaredMethod("run", HttpHost.class, HttpRequest.class, HttpContext.class),
8345            RestClient.class.getDeclaredMethod("execute", HttpHost.class, HttpRequest.class, HttpContext.class),
8346            RestClient.class.getDeclaredMethod("execute", HttpUriRequest.class, HttpContext.class));
8347      } catch (NoSuchMethodException e) {
8348         throw new ExceptionInInitializerError(e);
8349      }
8350   }
8351
8352   // Why this client cannot guarantee the SSRF guard of @Remote calls, or null if it can.  A connection manager this
8353   // client did not build has no pinned pool, an HttpClient other than the one the default createHttpClient() wired to
8354   // it (builtGuard) does not use it, and builderRefusal says why the HttpClientBuilder may have built the client around
8355   // something else.  The guard travels on each request's context, so it holds on another thread as long as the request
8356   // that carries it is the one sent; but anything that may send a different request (a custom call handler, a handler
8357   // bound to another client, a subclass that overrides the request dispatch: each may copy the request, or send it with
8358   // another context) is refused, and these refusals are what keep such paths from going out unpinned.
8359   private String ssrfRefusal(SsrfGuardConnectionManager builtGuard, String builderRefusal) {
8360      var tail = "the SSRF guardrail's connect-time contract (pin-on-connect + redirect revalidation) is not in force.  ";
8361      var optOut = "or set allowPrivateUrls(true) if this is an intentional local-dev/intranet target.";
8362      if (ssrfGuard == null && nn(builtGuard) && ! SsrfGuardConnectionManager.canCheckWiring())
8363         // HTT: only an HttpClient release whose InternalHttpClient has no connManager field, or a JVM that denies
8364         // reflective access to it, gets here.
8365         return "Refusing to send a policy-covered @Remote request: this RestClient cannot read the connection manager of "
8366            + "the HttpClient it built (org.apache.http.impl.client.InternalHttpClient.connManager), so it cannot confirm "
8367            + "that the client uses its SSRF-guard connection manager, and " + tail + "Use an HttpClient 4.5.x release, "
8368            + optOut;
8369      if (ssrfGuard == null && nn(builtGuard))
8370         return "Refusing to send a policy-covered @Remote request through an HttpClient that is not the one this RestClient "
8371            + "wired to its SSRF-guard connection manager: an overridden createHttpClient() or HttpClientBuilder.build() "
8372            + "returned another client, or a wrapper around one, which may send the request without the pinned pool, so "
8373            + tail + "Return the client super.createHttpClient() or HttpClientBuilder.build() built, unwrapped (customize it "
8374            + "through httpClientBuilder(...) instead), " + optOut;
8375      if (nn(builderRefusal))
8376         return builderRefusal;
8377      if (ssrfGuard == null)
8378         return "Refusing to send a policy-covered @Remote request through a caller-supplied HttpClient or connection "
8379            + "manager that cannot be guaranteed to honor the SSRF guardrail's connect-time contract (pin-on-connect + "
8380            + "redirect revalidation): the client was supplied via httpClient(...) or an overridden createHttpClient(), "
8381            + "or the connection manager via connectionManager(...) or an overridden createConnectionManager(), instead "
8382            + "of being built by this RestClient.  Let this RestClient build its own HttpClient and connection manager, "
8383            + optOut;
8384      if (callHandler.getClass() != BasicRestCallHandler.class)
8385         return "Refusing to send a policy-covered @Remote request through a custom RestCallHandler (" + cn(callHandler)
8386            + "): it may copy the request, or send it with another context, without the SSRF guard the request carries, so "
8387            + tail + "Remove the callHandler(...) setting, " + optOut;
8388      if (((BasicRestCallHandler)callHandler).client() != this)
8389         return "Refusing to send a policy-covered @Remote request through a BasicRestCallHandler bound to a different "
8390            + "RestClient: it sends the request through that client's connection manager, where " + tail
8391            + "Remove the callHandler(...) setting, " + optOut;
8392      var dispatch = overriddenDispatch(getClass());
8393      if (nn(dispatch))
8394         return "Refusing to send a policy-covered @Remote request through a RestClient subclass (" + dispatch
8395            + "): the override may copy the request, or send it with another context, without the SSRF guard the request "
8396            + "carries, so " + tail + "Remove the override, " + optOut;
8397      return null;
8398   }
8399
8400   // Why a guarded call cannot be sent through rc (the request createRequest(...) returned), or null if it can: a request
8401   // bound to another client goes out through that client's HttpClient, and an override of RestRequest.run() may copy
8402   // the request, or send it with another context, without the guard it carries.
8403   private String requestRefusal(RestRequest rc) {
8404      if (rc.client != this)
8405         return "Refusing to send a policy-covered @Remote request through a RestRequest bound to a different "
8406            + "RestClient: it sends the request through that client's HttpClient, where the SSRF guardrail's "
8407            + "connect-time contract (pin-on-connect + redirect revalidation) is not in force.  Remove the "
8408            + "createRequest(...) or request(...) override that returns it, or set allowPrivateUrls(true) if this is "
8409            + "an intentional local-dev/intranet target.";
8410      for (Class<?> x = rc.getClass(); x != RestRequest.class; x = x.getSuperclass()) {
8411         try {
8412            x.getDeclaredMethod("run");
8413            return "Refusing to send a policy-covered @Remote request through a RestRequest subclass (" + cn(x)
8414               + " overrides run()): the override may copy the request, or send it with another context, without the "
8415               + "SSRF guard the request carries, so the SSRF guardrail's connect-time contract (pin-on-connect + redirect revalidation) is not in force.  Remove the override "
8416               + "(or the createRequest(...) override that returns it), or set allowPrivateUrls(true) if this is an "
8417               + "intentional local-dev/intranet target.";
8418         } catch (@SuppressWarnings("unused") NoSuchMethodException e) { /* Not declared here. */ }
8419      }
8420      return null;
8421   }
8422
8423   // Returns "<class>.<method>(<params>)" for the first dispatch method a subclass between c and RestClient declares,
8424   // or null if there is none.
8425   private static String overriddenDispatch(Class<?> c) {
8426      for (var x = c; x != RestClient.class; x = x.getSuperclass()) {
8427         for (var m : DISPATCH_METHODS) {
8428            try {
8429               x.getDeclaredMethod(m.getName(), m.getParameterTypes());
8430               return cn(x) + " overrides " + m.getName() + "(" + String.join(",", Arrays.stream(m.getParameterTypes()).map(Class::getSimpleName).toList()) + ")";
8431            } catch (@SuppressWarnings("unused") NoSuchMethodException e) { /* Not declared here. */ }
8432         }
8433      }
8434      return null;
8435   }
8436
8437   /**
8438    * Resolves the effective request URL for a remote-proxy call, applying the dynamic-URL overrides
8439    * ({@code @Url} parameter, then method-level {@code baseUrl}, then interface-level {@code baseUrl}) over the
8440    * statically-computed interface-base + method path, with the http/https SSRF guardrail.
8441    *
8442    * <p>
8443    * Ported from the next-generation engine's {@code RemoteInvocationHandler.resolveEffectiveUrl(...)}.
8444    */
8445   String resolveRemoteUri(Class<?> interfaceClass, String restUrl2, Method method, RemoteOperationMeta rom, RemoteMeta rm, Object[] args) {
8446      var fullPath = rom.getFullPath();
8447      var allowPrivate = isAllowPrivateUrls() || rm.isAllowPrivateUrls();
8448      String uri;
8449
8450      // Option A: a call-time @Url parameter wins over everything (endpoint replacement).
8451      var urlIdx = rom.getUrlParamIndex();
8452      if (urlIdx >= 0) {
8453         var arg = (args == null || urlIdx >= args.length) ? null : args[urlIdx];
8454         var v = arg == null ? null : arg.toString();
8455         if (ib(v))
8456            throw new RemoteMetadataException(interfaceClass, "@Url parameter on " + method.getDeclaringClass().getName() + "." + method.getName() + " must not be null or blank.");
8457         uri = RemoteProxyUtils.requireHttpScheme(v.trim(), allowPrivate, allowedAddressRanges);
8458         // A scheme-less @Url value is relative and resolved against the client root URL only.
8459         if (uri.indexOf("://") == -1)
8460            uri = restUrl2 + '/' + trimSlashes(uri);
8461      } else {
8462         // Option B: a declarative base/host override (method-level wins over interface-level).
8463         var baseUrl = firstNonEmpty(rom.getBaseUrl(), rm.getBaseUrl());
8464         if (ine(baseUrl)) {
8465            uri = RemoteProxyUtils.requireHttpScheme(RemoteProxyUtils.combinePaths(baseUrl, fullPath), allowPrivate, allowedAddressRanges);
8466         } else {
8467            uri = fullPath;
8468            if (uri.indexOf("://") == -1)
8469               uri = restUrl2 + '/' + uri;
8470         }
8471      }
8472
8473      if (uri.indexOf("://") == -1)
8474         throw new RemoteMetadataException(interfaceClass, "Root URI has not been specified.  Cannot construct absolute path to remote resource.");
8475
8476      // SSRF guardrail (parity with juneau-rest-client RemoteClient.resolveEffectiveUrl): the fully-resolved
8477      // absolute URI -- including a scheme-less @Url/default-path combined with the client root above -- must pass
8478      // the full deny-private policy, not just the http/https scheme check (Review R4: the default (no-override)
8479      // path is policy-covered too once it is absolute).
8480      try {
8481         RemoteUrlPolicy.requireAllowedUrl(uri, allowPrivate, allowedAddressRanges);
8482      } catch (IllegalArgumentException e) {
8483         throw new RemoteMetadataException(interfaceClass, e.getMessage());
8484      }
8485
8486      return uri;
8487   }
8488
8489   /**
8490    * Builds a fresh {@link RestRequest} for a remote-proxy call, binding constant parts (interface + method level),
8491    * content-negotiation overrides ({@code accept}/{@code contentType}), the method-argument parts, and the per-call
8492    * timeout.  Re-invoked per retry attempt so a (gated) retry resends a freshly-bound request.
8493    *
8494    * <p>
8495    * Ported from the next-generation engine's {@code RemoteInvocationHandler.buildRequest(...)}.  Unlike the NG
8496    * version, argument binding here is driven entirely by the pre-resolved {@link RemoteOperationMeta} (<c>rom</c>)
8497    * rather than live reflection over the interface {@link Method}, and any misconfiguration that needs to identify
8498    * the offending interface/method is already reported earlier by {@link #resolveRemoteUri}; neither the interface
8499    * class nor the {@link Method} is needed here.
8500    */
8501   RestRequest buildRemoteRequest(String uri, Serializer serializer, Parser parser, RemoteOperationMeta rom, RemoteMeta rm, Object[] args) throws RestCallException {
8502      var httpMethod = rom.getHttpMethod();
8503      var rc = request(httpMethod, uri, hasContent(httpMethod));
8504
8505      if (serializer != null) rc.serializer(serializer);
8506      if (parser != null) rc.parser(parser);
8507
8508      // contentType override: select the matching registered serializer (else the client default) and send the
8509      // overridden media type as the Content-Type label (mirrors NG resolveBodyFormat()).
8510      var effContentType = firstNonEmpty(rom.getContentType(), rm.getContentType());
8511      if (ine(effContentType)) {
8512         var s = getMatchingSerializer(effContentType);
8513         if (s == null) {
8514            var all = serializers.getSerializers();
8515            if (! all.isEmpty())
8516               s = all.get(0);
8517         }
8518         if (nn(s))
8519            rc.serializer(s);
8520         rc.contentType(effContentType);
8521      }
8522
8523      var effAccept = firstNonEmpty(rom.getAccept(), rm.getAccept());
8524
8525      // Constant headers (interface-level then method-level, method-level wins on name collisions).  A constant
8526      // Content-Type/Accept is dropped when the dedicated contentType/accept attribute is in effect.
8527      var methodHeaderNames = new HashSet<String>();
8528      rom.getConstantHeaders().forEach(e -> methodHeaderNames.add(e.getKey()));
8529      var skipContentType = ine(effContentType);
8530      var skipAccept = ine(effAccept);
8531      rm.getHeaders().forEach(h -> {
8532         var n = h.getName();
8533         if (methodHeaderNames.contains(n))
8534            return;
8535         if (skipContentType && eqic(HEADER_CONTENT_TYPE, n))
8536            return;
8537         if (skipAccept && eqic(HEADER_ACCEPT, n))
8538            return;
8539         rc.header(h);
8540      });
8541      rom.getConstantHeaders().forEach(e -> {
8542         if (skipContentType && eqic(HEADER_CONTENT_TYPE, e.getKey()))
8543            return;
8544         if (skipAccept && eqic(HEADER_ACCEPT, e.getKey()))
8545            return;
8546         rc.header(e.getKey(), e.getValue());
8547      });
8548
8549      // Constant query/form-data (interface-level then method-level, method-level wins on name collisions).
8550      RemoteProxyUtils.mergeConstants(rm.getQueryData(), rom.getConstantQueryData()).forEach(rc::queryData);
8551      RemoteProxyUtils.mergeConstants(rm.getFormData(), rom.getConstantFormData()).forEach(rc::formData);
8552
8553      // Apply method-level defaults if parameter values are not provided (9.2.0)
8554      rom.forEachPathArg(a -> {
8555         var val = args[a.getIndex()];
8556         if (val == null) {
8557            var def = a.getSchema().getDefault();
8558            if (def == null)
8559               def = rom.getPathDefault(a.getName());
8560            if (nn(def))
8561               val = def;
8562         }
8563         rc.pathArg(a.getName(), val, a.getSchema(), a.getSerializer().orElse(partSerializer));
8564      });
8565      rom.forEachQueryArg(a -> {
8566         var val = args[a.getIndex()];
8567         if (val == null) {
8568            var def = a.getSchema().getDefault();
8569            if (def == null)
8570               def = rom.getQueryDefault(a.getName());
8571            if (nn(def))
8572               val = def;
8573         }
8574         rc.queryArg(a.getName(), val, a.getSchema(), a.getSerializer().orElse(partSerializer), a.isSkipIfEmpty());
8575      });
8576      rom.forEachFormDataArg(a -> {
8577         var val = args[a.getIndex()];
8578         if (val == null) {
8579            var def = a.getSchema().getDefault();
8580            if (def == null)
8581               def = rom.getFormDataDefault(a.getName());
8582            if (nn(def))
8583               val = def;
8584         }
8585         rc.formDataArg(a.getName(), val, a.getSchema(), a.getSerializer().orElse(partSerializer), a.isSkipIfEmpty());
8586      });
8587      rom.forEachHeaderArg(a -> {
8588         var val = args[a.getIndex()];
8589         if (val == null) {
8590            var def = a.getSchema().getDefault();
8591            if (def == null)
8592               def = rom.getHeaderDefault(a.getName());
8593            if (nn(def))
8594               val = def;
8595         }
8596         rc.headerArg(a.getName(), val, a.getSchema(), a.getSerializer().orElse(partSerializer), a.isSkipIfEmpty());
8597      });
8598
8599      var ba = rom.getContentArg();
8600      if (nn(ba)) {
8601         var val = args[ba.getIndex()];
8602         if (val == null) {
8603            var def = ba.getSchema().getDefault();
8604            if (def == null)
8605               def = rom.getContentDefault();
8606            if (nn(def))
8607               val = def;
8608         }
8609         rc.content(val, ba.getSchema());
8610      } else {
8611         var contentDef = rom.getContentDefault();
8612         if (nn(contentDef))
8613            rc.content(contentDef);
8614      }
8615
8616      rom.forEachRequestArg(rmba -> {
8617         var rbm = rmba.getMeta();
8618         var bean = args[rmba.getIndex()];
8619         if (nn(bean)) {
8620            for (var p : rbm.getProperties()) {
8621               var val = safeSupplier(() -> p.getGetter().invoke(bean));
8622               if (val instanceof Optional<?> val2)
8623                  val = val2.orElse(null);
8624               var pt = p.getPartType();
8625               var pn = p.getPartName();
8626               var schema = p.getSchema();
8627               if (pt == PATH)
8628                  rc.pathArg(pn, val, schema, p.getSerializer().orElse(partSerializer));
8629               else if (nn(val)) {
8630                  if (pt == QUERY)
8631                     rc.queryArg(pn, val, schema, p.getSerializer().orElse(partSerializer), schema.isSkipIfEmpty());
8632                  else if (pt == FORMDATA)
8633                     rc.formDataArg(pn, val, schema, p.getSerializer().orElse(partSerializer), schema.isSkipIfEmpty());
8634                  else if (pt == HEADER)
8635                     rc.headerArg(pn, val, schema, p.getSerializer().orElse(partSerializer), schema.isSkipIfEmpty());
8636                  else /* (pt == HttpPartType.BODY) */
8637                     rc.content(val, schema);
8638               }
8639            }
8640         }
8641      });
8642
8643      // Set the Accept header from the dedicated attribute unless a caller-supplied @Header param already provided one.
8644      if (ine(effAccept) && ! rc.containsHeader(HEADER_ACCEPT))
8645         rc.accept(effAccept);
8646
8647      // Per-call response/read timeout (method-level overrides interface-level) via a per-call RequestConfig.
8648      var effTimeout = firstNonEmpty(rom.getTimeout(), rm.getTimeout());
8649      if (ine(effTimeout)) {
8650         var ms = getDuration(effTimeout);
8651         if (ms > 0) {
8652            var base = rc.getConfig();
8653            var cb = base != null ? RequestConfig.copy(base) : RequestConfig.custom();
8654            rc.config(cb.setSocketTimeout((int)ms).build());
8655         }
8656      }
8657
8658      return rc;
8659   }
8660
8661   /**
8662    * Executes a remote-proxy call and processes the return value, applying safe automatic retries when the method
8663    * opts in and all safety gates pass (idempotent verb or {@code retryNonIdempotent}, buffered return mode, and a
8664    * repeatable body).  Mirrors the next-generation engine's {@code RemoteInvocationHandler.processReturn(...)}.
8665    */
8666   @SuppressWarnings({
8667      "java:S135" // Two continue statements are the two retry triggers (transport failure, retryable status); merging them would obscure the loop
8668   })
8669   Object executeRemoteWithRetry(String uri, Serializer serializer, Parser parser, Method method, RemoteOperationMeta rom, RemoteMeta rm, Object[] args) throws Exception {
8670      var throwOnError = rm.isThrowOnError() || rom.isThrowOnError();
8671      var ror = rom.getReturns();
8672      var maxRetries = (isRetryableMode(ror, method.getReturnType()) && isRetryableVerb(rom, rm)) ? effectiveRetries(rom, rm) : 0;
8673
8674      // Every getRemote() call is policy-covered; the SSRF guard is active unless allowPrivateUrls opts out.
8675      var allowPrivate = isAllowPrivateUrls() || rm.isAllowPrivateUrls();
8676      var guardActive = ! allowPrivate;
8677      if (guardActive && ! ssrfPolicySupported)
8678         throw new RestCallException(null, null, "%s", ssrfRefusal);
8679
8680      var attempt = 0;
8681      while (true) {
8682         var rc = buildRemoteRequest(uri, serializer, parser, rom, rm, args);
8683         rc.rethrow(RuntimeException.class);
8684         rom.forEachException(rc::rethrow);
8685         // The classic run() throws by default on >=400; the proxy replicates NG's throwIfError() instead, so it
8686         // always suppresses that generic throw and applies the typed/conditional mapping itself.
8687         rc.ignoreErrors();
8688         if (guardActive) {
8689            var refusal = requestRefusal(rc);
8690            if (nn(refusal))
8691               throw new RestCallException(null, null, "%s", refusal);
8692            // Carried on the request's context, so the guard holds on whichever thread the request is sent.
8693            rc.ssrfGuard();
8694         }
8695
8696         // Non-repeatable body: never retry (resending a consumed stream would corrupt the call).
8697         var canRetry = maxRetries > 0 && (attempt > 0 || rc.isBodyRepeatable());
8698
8699         RestResponse res;
8700         if (guardActive)
8701            RemoteUrlPolicyState.activate();
8702         try {
8703            res = rc.run();
8704         } catch (SsrfGuardConnectionManager.GuardRefusedException e) {
8705            // Reported like the other guard refusals (and other transport failures), not as a raw runtime exception.
8706            throw new RestCallException(null, e, "%s", e.getMessage());
8707         } catch (RestCallException e) {
8708            // A transport failure (IOException cause) is retryable; a reconstructed server exception is not
8709            // caught here (it is not a RestCallException).
8710            if (canRetry && attempt < maxRetries && e.getCause() instanceof IOException) {
8711               attempt++;
8712               backoff(attempt);
8713               continue;
8714            }
8715            Throwable t = e.getCause();
8716            if (t instanceof RuntimeException t2)
8717               throw t2;
8718            if (t instanceof Exception t2) {
8719               for (var t3 : method.getExceptionTypes())
8720                  if (t3.isInstance(t2))
8721                     throw t2;
8722            }
8723            throw toRex(e);
8724         } finally {
8725            if (guardActive)
8726               RemoteUrlPolicyState.deactivate();
8727         }
8728
8729         if (canRetry && attempt < maxRetries && isRetryableStatus(res.getStatusCode())) {
8730            res.close();
8731            attempt++;
8732            backoff(attempt);
8733            continue;
8734         }
8735
8736         return materializeRemote(res, method, rom, throwOnError);
8737      }
8738   }
8739
8740   /**
8741    * Materializes the terminal return value from an already-run response, applying the typed-exception /
8742    * conditional-throw error mapping (mirrors the next-generation engine's {@code throwIfError} +
8743    * {@code materializeResponse}).
8744    */
8745   Object materializeRemote(RestResponse res, Method method, RemoteOperationMeta rom, boolean throwOnError) throws Exception {
8746      var ror = rom.getReturns();
8747      var rv = ror.getReturnValue();
8748
8749      if (rv == RemoteReturn.NONE) {
8750         res.close();
8751         return null;
8752      }
8753      if (rv == RemoteReturn.STATUS) {
8754         var sc = res.getStatusCode();
8755         var rt = method.getReturnType();
8756         res.close();
8757         if (rt == Integer.class || rt == int.class)
8758            return sc;
8759         if (rt == Boolean.class || rt == boolean.class)
8760            return sc < 400;
8761         throw new RestCallException(res, null, "Invalid return type on method annotated with @RemoteOp(returns=RemoteReturn.STATUS).  Only integer and booleans types are valid.");
8762      }
8763      if (rv == RemoteReturn.RESPONSE)
8764         return res;
8765      if (rv == RemoteReturn.BEAN) {
8766         throwRemoteError(res, method, throwOnError);
8767         return res.as(ror.getResponseBeanMeta());
8768      }
8769      // BODY (default)
8770      throwRemoteError(res, method, throwOnError);
8771      var rt = method.getReturnType();
8772      Object v = res.getContent().as(ror.getReturnType());
8773      if (v == null && rt.isPrimitive())
8774         v = ClassInfo.of(rt).getPrimitiveDefault();
8775      return v;
8776   }
8777
8778   /**
8779    * Maps an error HTTP status (&ge;400) to a typed exception declared in the method's {@code throws} clause (a
8780    * {@link org.apache.juneau.http.response.BasicHttpException} subtype whose {@code STATUS_CODE} matches), else
8781    * conditionally throws a generic exception when {@code throwOnError} is set, else lets the error body flow through
8782    * as the return value.  Mirrors the next-generation engine's {@code throwIfError(...)}.
8783    */
8784   void throwRemoteError(RestResponse res, Method method, boolean throwOnError) throws Exception {
8785      var sc = res.getStatusCode();
8786      if (sc < 400)
8787         return;
8788      for (var et : method.getExceptionTypes()) {
8789         if (org.apache.juneau.http.response.BasicHttpException.class.isAssignableFrom(et) && httpStatusCode(et) == sc) {
8790            var body = res.getContent().asString();
8791            res.close();
8792            throw (org.apache.juneau.http.response.BasicHttpException) instantiateHttpType(et, body);
8793         }
8794      }
8795      if (throwOnError) {
8796         var body = res.getContent().asString();
8797         res.close();
8798         throw new org.apache.juneau.http.response.BasicHttpException(sc, body);
8799      }
8800      // else: let the error body flow through as the return value (parity with NG throwOnError=false).
8801   }
8802
8803   /** Returns the static {@code STATUS_CODE} field of an HTTP response/exception type, or {@code -1} if absent. */
8804   private static int httpStatusCode(Class<?> c) {
8805      try {
8806         return c.getField("STATUS_CODE").getInt(null);
8807      } catch (ReflectiveOperationException e) {
8808         return -1;
8809      }
8810   }
8811
8812   /** Instantiates an HTTP response/exception bean, preferring a {@code (String body)} constructor. */
8813   private static Object instantiateHttpType(Class<?> c, String body) {
8814      try {
8815         return newHttpTypeInstance(c, body);
8816      } catch (ReflectiveOperationException e) {
8817         throw rex(e, "Could not instantiate HTTP response/exception type %s", c.getName());
8818      }
8819   }
8820
8821   private static Object newHttpTypeInstance(Class<?> c, String body) throws ReflectiveOperationException {
8822      try {
8823         return c.getConstructor(String.class).newInstance(body);
8824      } catch (NoSuchMethodException e) {
8825         return c.getConstructor().newInstance();
8826      }
8827   }
8828
8829   /** Returns <jk>true</jk> if the return mode/type is a buffered (retryable) shape, not a streaming/wrapper one. */
8830   private static boolean isRetryableMode(RemoteOperationReturn ror, Class<?> returnType) {
8831      if (ror.getReturnValue() == RemoteReturn.RESPONSE)
8832         return false;
8833      if (ror.isFuture() || ror.isCompletableFuture())
8834         return false;
8835      return ! (returnType == InputStream.class || returnType == Reader.class || returnType == Optional.class);
8836   }
8837
8838   /** Returns <jk>true</jk> if the verb may auto-retry: idempotent verbs always, POST/PATCH only when opted in. */
8839   private static boolean isRetryableVerb(RemoteOperationMeta rom, RemoteMeta rm) {
8840      if (isOneOf(rom.getHttpMethod(), "GET", "PUT", "DELETE", "HEAD"))
8841         return true;
8842      return rom.isRetryNonIdempotent() || rm.isRetryNonIdempotent();
8843   }
8844
8845   /** Returns the effective retry count: a positive method-level value overrides the interface-level default. */
8846   private static int effectiveRetries(RemoteOperationMeta rom, RemoteMeta rm) {
8847      return rom.getRetries() > 0 ? rom.getRetries() : rm.getRetries();
8848   }
8849
8850   /** Retryable HTTP statuses: {@code 429} (Too Many Requests) and all {@code 5xx} server errors. */
8851   private static boolean isRetryableStatus(int statusCode) {
8852      return statusCode == 429 || statusCode >= 500;
8853   }
8854
8855   /** Sleeps a short exponential backoff ({@code 50ms * 2^(attempt-1)}, capped at {@code 1s}) before a retry. */
8856   private static void backoff(int attempt) {
8857      try {
8858         Thread.sleep(Math.min(50L << (attempt - 1), 1000L));
8859      } catch (InterruptedException e) {
8860         Thread.currentThread().interrupt();
8861      }
8862   }
8863
8864   ExecutorService getExecutorService() {
8865      ExecutorService result = executorService.get();
8866      if (nn(result))
8867         return result;
8868      synchronized (this) {
8869         result = executorService.get();
8870         if (nn(result))
8871            return result;
8872         result = new ThreadPoolExecutor(1, 1, 30, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10));
8873         executorService.set(result);
8874         return result;
8875      }
8876   }
8877
8878   <T extends Context> T getInstance(Class<T> c) {
8879      var o = requestContexts.computeIfAbsent(c, k -> {
8880         if (Serializer.class.isAssignableFrom(k)) {
8881            return Serializer.createSerializerBuilder((Class<? extends Serializer>)k).marshallingContext(getMarshallingContext()).build();
8882         } else if (Parser.class.isAssignableFrom(k)) {
8883            return Parser.createParserBuilder((Class<? extends Parser>)k).marshallingContext(getMarshallingContext()).build();
8884         }
8885         return null;
8886      });
8887      return (T)o;
8888   }
8889
8890   /*
8891    * Returns the parser that best matches the specified content type.
8892    * If no match found or the content type is <jk>null</jk>, returns the parser in the list if it's a list of one.
8893    * Returns <jk>null</jk> if no parsers are defined.
8894    */
8895   Parser getMatchingParser(String mediaType) {
8896      if (parsers.isEmpty())
8897         return null;
8898      if (nn(mediaType)) {
8899         var p = parsers.getParser(mediaType).orElse(null);
8900         if (nn(p))
8901            return p;
8902      }
8903      var l = parsers.getParsers();
8904      return (l.size() == 1 ? l.get(0) : null);
8905   }
8906
8907   /*
8908    * Returns the serializer that best matches the specified content type.
8909    * If no match found or the content type is <jk>null</jk>, returns the serializer in the list if it's a list of one.
8910    * Returns <jk>null</jk> if no serializers are defined.
8911    */
8912   Serializer getMatchingSerializer(String mediaType) {
8913      if (serializers.isEmpty())
8914         return null;
8915      if (nn(mediaType)) {
8916         var s = serializers.getSerializer(mediaType).orElse(null);
8917         if (nn(s))
8918            return s;
8919      }
8920      var l = serializers.getSerializers();
8921      return (l.size() == 1 ? l.get(0) : null);
8922   }
8923
8924   boolean hasParsers() {
8925      return ! parsers.getParsers().isEmpty();
8926   }
8927
8928   boolean hasSerializers() {
8929      return ! serializers.getSerializers().isEmpty();
8930   }
8931
8932   URI toUri(Object x, String rootUrl) throws RestCallException {
8933      try {
8934         if (x instanceof URI x2)
8935            return x2;
8936         if (x instanceof URL x2)
8937            return x2.toURI();
8938         if (x instanceof URIBuilder x2)
8939            return x2.build();
8940         var s = x == null ? "" : x.toString();
8941         if (nn(rootUrl) && ! absUrlPattern.matcher(s).matches()) {
8942            if (s.isEmpty())
8943               s = rootUrl;
8944            else {
8945               var sb = new StringBuilder(rootUrl);
8946               if (! s.startsWith("/"))
8947                  sb.append('/');
8948               sb.append(s);
8949               s = sb.toString();
8950            }
8951         }
8952         s = fixUrl(s);
8953         return new URI(s);
8954      } catch (URISyntaxException e) {
8955         throw new RestCallException(null, e, "Invalid URI encountered:  %s", x);  // Shouldn't happen.
8956      }
8957   }
8958}