001package org.jsoup;
002
003import org.jsoup.helper.RequestAuthenticator;
004import org.jsoup.nodes.Document;
005import org.jsoup.parser.Parser;
006import org.jspecify.annotations.Nullable;
007
008import javax.net.ssl.SSLSocketFactory;
009import java.io.BufferedInputStream;
010import java.io.IOException;
011import java.io.InputStream;
012import java.io.UncheckedIOException;
013import java.net.Authenticator;
014import java.net.CookieStore;
015import java.net.Proxy;
016import java.net.URL;
017import java.util.Collection;
018import java.util.List;
019import java.util.Map;
020
021/**
022 The Connection interface is a convenient HTTP client and session object to fetch content from the web, and parse them
023 into Documents.
024 <p>To start a new session, use either {@link org.jsoup.Jsoup#newSession()} or {@link org.jsoup.Jsoup#connect(String)}.
025 Connections contain {@link Connection.Request} and {@link Connection.Response} objects (once executed). Configuration
026 settings (URL, timeout, useragent, etc) set on a session will be applied by default to each subsequent request.</p>
027 <p>To start a new request from the session, use {@link #newRequest()}.</p>
028 <p>Cookies are stored in memory for the duration of the session. For that reason, do not use one single session for all
029 requests in a long-lived application, or you are likely to run out of memory, unless care is taken to clean up the
030 cookie store. The cookie store for the session is available via {@link #cookieStore()}. You may provide your own
031 implementation via {@link #cookieStore(java.net.CookieStore)} before making requests.</p>
032 <p>Request configuration can be made using either the shortcut methods in Connection (e.g. {@link #userAgent(String)}),
033 or by methods in the {@link Connection.Request} object directly. All request configuration must be made before the request is
034 executed. When used as an ongoing session, initialize all defaults prior to making multi-threaded {@link
035#newRequest()}s.</p>
036 <p>Note that the term "Connection" used here does not mean that a long-lived connection is held against a server for
037 the lifetime of the Connection object. A socket connection is only made at the point of request execution ({@link
038#execute()}, {@link #get()}, or {@link #post()}), and the server's response consumed.</p>
039 <p>For multi-threaded implementations, it is important to use a {@link #newRequest()} for each request. The session may
040 be shared across concurrent threads, but a not a specific request.</p>
041 */
042@SuppressWarnings("unused")
043public interface Connection {
044
045    /**
046     * GET and POST http methods.
047     */
048    enum Method {
049        GET(false), POST(true), PUT(true), DELETE(true), PATCH(true), HEAD(false), OPTIONS(false), TRACE(false);
050
051        private final boolean hasBody;
052
053        Method(boolean hasBody) {
054            this.hasBody = hasBody;
055        }
056
057        /**
058         * Check if this HTTP method has/needs a request body
059         * @return if body needed
060         */
061        public final boolean hasBody() {
062            return hasBody;
063        }
064    }
065
066    /**
067     Creates a new request, using this Connection as the session-state and to initialize the connection settings (which
068     may then be independently changed on the returned {@link Connection.Request} object).
069     @return a new Connection object, with a shared Cookie Store and initialized settings from this Connection and Request
070     @since 1.14.1
071     */
072    Connection newRequest();
073
074    /**
075     Creates a new request, using this Connection as the session-state and to initialize the connection settings (which
076     may then be independently changed on the returned {@link Connection.Request} object).
077     @return a new Connection object, with a shared Cookie Store and initialized settings from this Connection and Request
078     @param url URL for the new request
079     @since 1.17.1
080     */
081    default Connection newRequest(String url) {
082        return newRequest().url(url);
083    }
084
085    /**
086     Creates a new request, using this Connection as the session-state and to initialize the connection settings (which
087     may then be independently changed on the returned {@link Connection.Request} object).
088     @return a new Connection object, with a shared Cookie Store and initialized settings from this Connection and Request
089     @param url URL for the new request
090     @since 1.17.1
091     */
092    default Connection newRequest(URL url) {
093        return newRequest().url(url);
094    }
095
096    /**
097     * Set the request URL to fetch. The protocol must be HTTP or HTTPS.
098     * @param url URL to connect to
099     * @return this Connection, for chaining
100     */
101    Connection url(URL url);
102
103    /**
104     * Set the request URL to fetch. The protocol must be HTTP or HTTPS.
105     * @param url URL to connect to
106     * @return this Connection, for chaining
107     */
108    Connection url(String url);
109
110    /**
111     * Set the proxy to use for this request. Set to <code>null</code> to disable a previously set proxy.
112     * @param proxy proxy to use
113     * @return this Connection, for chaining
114     */
115    Connection proxy(@Nullable Proxy proxy);
116
117    /**
118     * Set the HTTP proxy to use for this request.
119     * @param host the proxy hostname
120     * @param port the proxy port
121     * @return this Connection, for chaining
122     */
123    Connection proxy(String host, int port);
124
125    /**
126     * Set the request user-agent header.
127     * @param userAgent user-agent to use
128     * @return this Connection, for chaining
129     * @see org.jsoup.helper.HttpConnection#DEFAULT_UA
130     */
131    Connection userAgent(String userAgent);
132
133    /**
134     * Set the total request timeout duration. If a timeout occurs, an {@link java.net.SocketTimeoutException} will be thrown.
135     * <p>The default timeout is <b>30 seconds</b> (30,000 millis). A timeout of zero is treated as an infinite timeout.
136     * <p>Note that this timeout specifies the combined maximum duration of the connection time and the time to read
137     * the full response.
138     * @param millis number of milliseconds (thousandths of a second) before timing out connects or reads.
139     * @return this Connection, for chaining
140     * @see #maxBodySize(int)
141     */
142    Connection timeout(int millis);
143
144    /**
145     * Set the maximum bytes to read from the (uncompressed) connection into the body, before the connection is closed,
146     * and the input truncated (i.e. the body content will be trimmed). <b>The default maximum is 2MB</b>. A max size of
147     * <code>0</code> is treated as an infinite amount (bounded only by your patience and the memory available on your
148     * machine).
149     *
150     * @param bytes number of bytes to read from the input before truncating
151     * @return this Connection, for chaining
152     */
153    Connection maxBodySize(int bytes);
154
155    /**
156     * Set the request referrer (aka "referer") header.
157     * @param referrer referrer to use
158     * @return this Connection, for chaining
159     */
160    Connection referrer(String referrer);
161
162    /**
163     * Configures the connection to (not) follow server redirects. By default, this is <b>true</b>.
164     * @param followRedirects true if server redirects should be followed.
165     * @return this Connection, for chaining
166     */
167    Connection followRedirects(boolean followRedirects);
168
169    /**
170     * Set the request method to use, GET or POST. Default is GET.
171     * @param method HTTP request method
172     * @return this Connection, for chaining
173     */
174    Connection method(Method method);
175
176    /**
177     * Configures the connection to not throw exceptions when an HTTP error occurs. (4xx - 5xx, e.g. 404 or 500). By
178     * default, this is <b>false</b>; an IOException is thrown if an error is encountered. If set to <b>true</b>, the
179     * response is populated with the error body, and the status message will reflect the error.
180     * @param ignoreHttpErrors - false (default) if HTTP errors should be ignored.
181     * @return this Connection, for chaining
182     */
183    Connection ignoreHttpErrors(boolean ignoreHttpErrors);
184
185    /**
186     * Ignore the document's Content-Type when parsing the response. By default, this is <b>false</b>, an unrecognised
187     * content-type will cause an IOException to be thrown. (This is to prevent producing garbage by attempting to parse
188     * a JPEG binary image, for example.) Set to true to force a parse attempt regardless of content type.
189     * @param ignoreContentType set to true if you would like the content type ignored on parsing the response into a
190     * Document.
191     * @return this Connection, for chaining
192     */
193    Connection ignoreContentType(boolean ignoreContentType);
194
195    /**
196     * Set custom SSL socket factory
197     * @param sslSocketFactory custom SSL socket factory
198     * @return this Connection, for chaining
199     */
200    Connection sslSocketFactory(SSLSocketFactory sslSocketFactory);
201
202    /**
203     * Add a request data parameter. Request parameters are sent in the request query string for GETs, and in the
204     * request body for POSTs. A request may have multiple values of the same name.
205     * @param key data key
206     * @param value data value
207     * @return this Connection, for chaining
208     */
209    Connection data(String key, String value);
210
211    /**
212     * Add an input stream as a request data parameter. For GETs, has no effect, but for POSTS this will upload the
213     * input stream.
214     * <p>Use the {@link #data(String, String, InputStream, String)} method to set the uploaded file's mimetype.</p>
215     * @param key data key (form item name)
216     * @param filename the name of the file to present to the remove server. Typically just the name, not path,
217     * component.
218     * @param inputStream the input stream to upload, that you probably obtained from a {@link java.io.FileInputStream}.
219     * You must close the InputStream in a {@code finally} block.
220     * @return this Connection, for chaining
221     * @see #data(String, String, InputStream, String)
222     */
223    Connection data(String key, String filename, InputStream inputStream);
224
225    /**
226     * Add an input stream as a request data parameter. For GETs, has no effect, but for POSTS this will upload the
227     * input stream.
228     * @param key data key (form item name)
229     * @param filename the name of the file to present to the remove server. Typically just the name, not path,
230     * component.
231     * @param inputStream the input stream to upload, that you probably obtained from a {@link java.io.FileInputStream}.
232     * @param contentType the Content Type (aka mimetype) to specify for this file.
233     * You must close the InputStream in a {@code finally} block.
234     * @return this Connection, for chaining
235     */
236    Connection data(String key, String filename, InputStream inputStream, String contentType);
237
238    /**
239     * Adds all of the supplied data to the request data parameters
240     * @param data collection of data parameters
241     * @return this Connection, for chaining
242     */
243    Connection data(Collection<KeyVal> data);
244
245    /**
246     * Adds all of the supplied data to the request data parameters
247     * @param data map of data parameters
248     * @return this Connection, for chaining
249     */
250    Connection data(Map<String, String> data);
251
252    /**
253     Add one or more request {@code key, val} data parameter pairs.
254     <p>Multiple parameters may be set at once, e.g.:
255     <code>.data("name", "jsoup", "language", "Java", "language", "English");</code> creates a query string like:
256     <code>{@literal ?name=jsoup&language=Java&language=English}</code></p>
257     <p>For GET requests, data parameters will be sent on the request query string. For POST (and other methods that
258     contain a body), they will be sent as body form parameters, unless the body is explicitly set by
259     {@link #requestBody(String)}, in which case they will be query string parameters.</p>
260
261     @param keyvals a set of key value pairs.
262     @return this Connection, for chaining
263     */
264    Connection data(String... keyvals);
265
266    /**
267     * Get the data KeyVal for this key, if any
268     * @param key the data key
269     * @return null if not set
270     */
271    @Nullable KeyVal data(String key);
272
273    /**
274     * Set a POST (or PUT) request body. Useful when a server expects a plain request body (such as JSON), and not a set
275     * of URL encoded form key/value pairs. E.g.:
276     * <code><pre>Jsoup.connect(url)
277     * .requestBody(json)
278     * .header("Content-Type", "application/json")
279     * .post();</pre></code>
280     * If any data key/vals are supplied, they will be sent as URL query params.
281     * @return this Request, for chaining
282     */
283    Connection requestBody(String body);
284
285    /**
286     * Set a request header. Replaces any existing header with the same case-insensitive name.
287     * @param name header name
288     * @param value header value
289     * @return this Connection, for chaining
290     * @see org.jsoup.Connection.Request#header(String, String)
291     * @see org.jsoup.Connection.Request#headers()
292     */
293    Connection header(String name, String value);
294
295    /**
296     * Sets each of the supplied headers on the request. Existing headers with the same case-insensitive name will be
297     * replaced with the new value.
298     * @param headers map of headers name {@literal ->} value pairs
299     * @return this Connection, for chaining
300     * @see org.jsoup.Connection.Request#headers()
301     */
302    Connection headers(Map<String,String> headers);
303
304    /**
305     * Set a cookie to be sent in the request.
306     * @param name name of cookie
307     * @param value value of cookie
308     * @return this Connection, for chaining
309     */
310    Connection cookie(String name, String value);
311
312    /**
313     * Adds each of the supplied cookies to the request.
314     * @param cookies map of cookie name {@literal ->} value pairs
315     * @return this Connection, for chaining
316     */
317    Connection cookies(Map<String, String> cookies);
318
319    /**
320     Provide a custom or pre-filled CookieStore to be used on requests made by this Connection.
321     @param cookieStore a cookie store to use for subsequent requests
322     @return this Connection, for chaining
323     @since 1.14.1
324     */
325    Connection cookieStore(CookieStore cookieStore);
326
327    /**
328     Get the cookie store used by this Connection.
329     @return the cookie store
330     @since 1.14.1
331     */
332    CookieStore cookieStore();
333
334    /**
335     * Provide a specific parser to use when parsing the response to a Document. If not set, jsoup defaults to the
336     * {@link Parser#htmlParser() HTML parser}, unless the response content-type is XML, in which case the
337     * {@link Parser#xmlParser() XML parser} is used.
338     * @param parser alternate parser
339     * @return this Connection, for chaining
340     */
341    Connection parser(Parser parser);
342
343    /**
344     * Set the character-set used to encode for x-www-form-urlencoded post data. Defaults to {@code UTF-8}.
345     * @param charset character set to encode post data
346     * @return this Connection, for chaining
347     */
348    Connection postDataCharset(String charset);
349
350    /**
351     Set the authenticator to use for this connection, enabling requests to URLs, and via proxies, that require
352     authentication credentials.
353     <p>The authentication scheme used is automatically detected during the request execution.
354     Supported schemes (subject to the platform) are {@code basic}, {@code digest}, {@code NTLM},
355     and {@code Kerberos}.</p>
356
357     <p>To use, supply a {@link RequestAuthenticator} function that:
358     <ol>
359     <li>validates the URL that is requesting authentication, and</li>
360     <li>returns the appropriate credentials (username and password)</li>
361     </ol>
362     </p>
363
364     <p>For example, to authenticate both to a proxy and a downstream web server:
365     <code><pre>
366     Connection session = Jsoup.newSession()
367         .proxy("proxy.example.com", 8080)
368         .auth(auth -> {
369             if (auth.isServer()) { // provide credentials for the request url
370                 Validate.isTrue(auth.url().getHost().equals("example.com"));
371                 // check that we're sending credentials were we expect, and not redirected out
372                 return auth.credentials("username", "password");
373             } else { // auth.isProxy()
374                 return auth.credentials("proxy-user", "proxy-password");
375             }
376         });
377
378     Connection.Response response = session.newRequest("https://example.com/adminzone/").execute();
379     </pre></code>
380     </p>
381
382     <p>The system may cache the authentication and use it for subsequent requests to the same resource.</p>
383
384     <p><b>Implementation notes</b></p>
385     <p>For compatibility, on a Java 8 platform, authentication is set up via the system-wide default
386     {@link java.net.Authenticator#setDefault(Authenticator)} method via a ThreadLocal delegator. Whilst the
387     authenticator used is request specific and thread-safe, if you have other calls to {@code setDefault}, they will be
388     incompatible with this implementation.</p>
389     <p>On Java 9 and above, the preceding note does not apply; authenticators are directly set on the request. </p>
390     <p>If you are attempting to authenticate to a proxy that uses the {@code basic} scheme and will be fetching HTTPS
391     URLs, you need to configure your Java platform to enable that, by setting the
392     {@code jdk.http.auth.tunneling.disabledSchemes} system property to {@code ""}.
393     This must be executed prior to any authorization attempts. E.g.:
394     <code><pre>
395     static {
396        System.setProperty("jdk.http.auth.tunneling.disabledSchemes", "");
397        // removes Basic, which is otherwise excluded from auth for CONNECT tunnels
398     }</pre></code>
399     </p>
400     * @param authenticator the authenticator to use in this connection
401     * @return this Connection, for chaining
402     * @since 1.17.1
403     */
404    default Connection auth(@Nullable RequestAuthenticator authenticator) {
405        throw new UnsupportedOperationException();
406    }
407
408    /**
409     * Execute the request as a GET, and parse the result.
410     * @return parsed Document
411     * @throws java.net.MalformedURLException if the request URL is not an HTTP or HTTPS URL, or is otherwise malformed
412     * @throws HttpStatusException if the response is not OK and HTTP response errors are not ignored
413     * @throws UnsupportedMimeTypeException if the response mime type is not supported and those errors are not ignored
414     * @throws java.net.SocketTimeoutException if the connection times out
415     * @throws IOException on error
416     */
417    Document get() throws IOException;
418
419    /**
420     * Execute the request as a POST, and parse the result.
421     * @return parsed Document
422     * @throws java.net.MalformedURLException if the request URL is not a HTTP or HTTPS URL, or is otherwise malformed
423     * @throws HttpStatusException if the response is not OK and HTTP response errors are not ignored
424     * @throws UnsupportedMimeTypeException if the response mime type is not supported and those errors are not ignored
425     * @throws java.net.SocketTimeoutException if the connection times out
426     * @throws IOException on error
427     */
428    Document post() throws IOException;
429
430    /**
431     * Execute the request.
432     * @return the executed {@link Response}
433     * @throws java.net.MalformedURLException if the request URL is not a HTTP or HTTPS URL, or is otherwise malformed
434     * @throws HttpStatusException if the response is not OK and HTTP response errors are not ignored
435     * @throws UnsupportedMimeTypeException if the response mime type is not supported and those errors are not ignored
436     * @throws java.net.SocketTimeoutException if the connection times out
437     * @throws IOException on error
438     */
439    Response execute() throws IOException;
440
441    /**
442     * Get the request object associated with this connection
443     * @return request
444     */
445    Request request();
446
447    /**
448     * Set the connection's request
449     * @param request new request object
450     * @return this Connection, for chaining
451     */
452    Connection request(Request request);
453
454    /**
455     * Get the response, once the request has been executed.
456     * @return response
457     * @throws IllegalArgumentException if called before the response has been executed.
458     */
459    Response response();
460
461    /**
462     * Set the connection's response
463     * @param response new response
464     * @return this Connection, for chaining
465     */
466    Connection response(Response response);
467
468    /**
469     * Common methods for Requests and Responses
470     * @param <T> Type of Base, either Request or Response
471     */
472    @SuppressWarnings("UnusedReturnValue")
473    interface Base<T extends Base<T>> {
474        /**
475         * Get the URL of this Request or Response. For redirected responses, this will be the final destination URL.
476         * @return URL
477         * @throws IllegalArgumentException if called on a Request that was created without a URL.
478         */
479        URL url();
480
481        /**
482         * Set the URL
483         * @param url new URL
484         * @return this, for chaining
485         */
486        T url(URL url);
487
488        /**
489         * Get the request method, which defaults to <code>GET</code>
490         * @return method
491         */
492        Method method();
493
494        /**
495         * Set the request method
496         * @param method new method
497         * @return this, for chaining
498         */
499        T method(Method method);
500
501        /**
502         * Get the value of a header. If there is more than one header value with the same name, the headers are returned
503         * comma separated, per <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2">rfc2616-sec4</a>.
504         * <p>
505         * Header names are case-insensitive.
506         * </p>
507         * @param name name of header (case-insensitive)
508         * @return value of header, or null if not set.
509         * @see #hasHeader(String)
510         * @see #cookie(String)
511         */
512        @Nullable String header(String name);
513
514        /**
515         * Get the values of a header.
516         * @param name header name, case-insensitive.
517         * @return a list of values for this header, or an empty list if not set.
518         */
519        List<String> headers(String name);
520
521        /**
522         * Set a header. This method will overwrite any existing header with the same case-insensitive name. If there
523         * is more than one value for this header, this method will update the first matching header.
524         * <p>For compatibility, if the content of the header includes text that cannot be represented by ISO-8859-1,
525         * then it should be encoded first per <a href="https://www.ietf.org/rfc/rfc2047.txt">RFC 2047</a>.</p>
526         * @param name Name of header
527         * @param value Value of header
528         * @return this, for chaining
529         * @see #addHeader(String, String)
530         */
531        T header(String name, String value);
532
533        /**
534         * Add a header. The header will be added regardless of whether a header with the same name already exists.
535         * <p>For compatibility, if the content of the header includes text that cannot be represented by ISO-8859-1,
536         * then it should be encoded first per <a href="https://www.ietf.org/rfc/rfc2047.txt">RFC 2047</a>.</p>
537         * @param name Name of new header
538         * @param value Value of new header
539         * @return this, for chaining
540         */
541        T addHeader(String name, String value);
542
543        /**
544         * Check if a header is present
545         * @param name name of header (case-insensitive)
546         * @return if the header is present in this request/response
547         */
548        boolean hasHeader(String name);
549
550        /**
551         * Check if a header is present, with the given value
552         * @param name header name (case-insensitive)
553         * @param value value (case-insensitive)
554         * @return if the header and value pair are set in this req/res
555         */
556        boolean hasHeaderWithValue(String name, String value);
557
558        /**
559         * Remove headers by name. If there is more than one header with this name, they will all be removed.
560         * @param name name of header to remove (case-insensitive)
561         * @return this, for chaining
562         */
563        T removeHeader(String name);
564
565        /**
566         * Retrieve all of the request/response header names and corresponding values as a map. For headers with multiple
567         * values, only the first header is returned.
568         * <p>Note that this is a view of the headers only, and changes made to this map will not be reflected in the
569         * request/response object.</p>
570         * @return headers
571         * @see #multiHeaders()
572
573         */
574        Map<String, String> headers();
575
576        /**
577         * Retreive all of the headers, keyed by the header name, and with a list of values per header.
578         * @return a list of multiple values per header.
579         */
580        Map<String, List<String>> multiHeaders();
581
582        /**
583         * Get a cookie value by name from this request/response.
584         * <p>
585         * Response objects have a simplified cookie model. Each cookie set in the response is added to the response
586         * object's cookie key=value map. The cookie's path, domain, and expiry date are ignored.
587         * </p>
588         * @param name name of cookie to retrieve.
589         * @return value of cookie, or null if not set
590         */
591        @Nullable String cookie(String name);
592
593        /**
594         * Set a cookie in this request/response.
595         * @param name name of cookie
596         * @param value value of cookie
597         * @return this, for chaining
598         */
599        T cookie(String name, String value);
600
601        /**
602         * Check if a cookie is present
603         * @param name name of cookie
604         * @return if the cookie is present in this request/response
605         */
606        boolean hasCookie(String name);
607
608        /**
609         * Remove a cookie by name
610         * @param name name of cookie to remove
611         * @return this, for chaining
612         */
613        T removeCookie(String name);
614
615        /**
616         * Retrieve all of the request/response cookies as a map
617         * @return cookies
618         */
619        Map<String, String> cookies();
620    }
621
622    /**
623     * Represents a HTTP request.
624     */
625    @SuppressWarnings("UnusedReturnValue")
626    interface Request extends Base<Request> {
627        /**
628         * Get the proxy used for this request.
629         * @return the proxy; <code>null</code> if not enabled.
630         */
631        @Nullable Proxy proxy();
632
633        /**
634         * Update the proxy for this request.
635         * @param proxy the proxy ot use; <code>null</code> to disable.
636         * @return this Request, for chaining
637         */
638        Request proxy(@Nullable Proxy proxy);
639
640        /**
641         * Set the HTTP proxy to use for this request.
642         * @param host the proxy hostname
643         * @param port the proxy port
644         * @return this Connection, for chaining
645         */
646        Request proxy(String host, int port);
647
648        /**
649         * Get the request timeout, in milliseconds.
650         * @return the timeout in milliseconds.
651         */
652        int timeout();
653
654        /**
655         * Update the request timeout.
656         * @param millis timeout, in milliseconds
657         * @return this Request, for chaining
658         */
659        Request timeout(int millis);
660
661        /**
662         * Get the maximum body size, in bytes.
663         * @return the maximum body size, in bytes.
664         */
665        int maxBodySize();
666
667        /**
668         * Update the maximum body size, in bytes.
669         * @param bytes maximum body size, in bytes.
670         * @return this Request, for chaining
671         */
672        Request maxBodySize(int bytes);
673
674        /**
675         * Get the current followRedirects configuration.
676         * @return true if followRedirects is enabled.
677         */
678        boolean followRedirects();
679
680        /**
681         * Configures the request to (not) follow server redirects. By default this is <b>true</b>.
682         * @param followRedirects true if server redirects should be followed.
683         * @return this Request, for chaining
684         */
685        Request followRedirects(boolean followRedirects);
686
687        /**
688         * Get the current ignoreHttpErrors configuration.
689         * @return true if errors will be ignored; false (default) if HTTP errors will cause an IOException to be
690         * thrown.
691         */
692        boolean ignoreHttpErrors();
693
694        /**
695         * Configures the request to ignore HTTP errors in the response.
696         * @param ignoreHttpErrors set to true to ignore HTTP errors.
697         * @return this Request, for chaining
698         */
699        Request ignoreHttpErrors(boolean ignoreHttpErrors);
700
701        /**
702         * Get the current ignoreContentType configuration.
703         * @return true if invalid content-types will be ignored; false (default) if they will cause an IOException to
704         * be thrown.
705         */
706        boolean ignoreContentType();
707
708        /**
709         * Configures the request to ignore the Content-Type of the response.
710         * @param ignoreContentType set to true to ignore the content type.
711         * @return this Request, for chaining
712         */
713        Request ignoreContentType(boolean ignoreContentType);
714
715        /**
716         * Get the current custom SSL socket factory, if any.
717         * @return custom SSL socket factory if set, null otherwise
718         */
719        @Nullable SSLSocketFactory sslSocketFactory();
720
721        /**
722         * Set a custom SSL socket factory.
723         * @param sslSocketFactory SSL socket factory
724         */
725        void sslSocketFactory(SSLSocketFactory sslSocketFactory);
726
727        /**
728         * Add a data parameter to the request
729         * @param keyval data to add.
730         * @return this Request, for chaining
731         */
732        Request data(KeyVal keyval);
733
734        /**
735         * Get all of the request's data parameters
736         * @return collection of keyvals
737         */
738        Collection<KeyVal> data();
739
740        /**
741         * Set a POST (or PUT) request body. Useful when a server expects a plain request body, not a set of URL
742         * encoded form key/value pairs. E.g.:
743         * <code><pre>Jsoup.connect(url)
744         * .requestBody(json)
745         * .header("Content-Type", "application/json")
746         * .post();</pre></code>
747         * If any data key/vals are supplied, they will be sent as URL query params.
748         * @param body to use as the request body. Set to null to clear a previously set body.
749         * @return this Request, for chaining
750         */
751        Request requestBody(@Nullable String body);
752
753        /**
754         * Get the current request body.
755         * @return null if not set.
756         */
757        @Nullable String requestBody();
758
759        /**
760         * Specify the parser to use when parsing the document.
761         * @param parser parser to use.
762         * @return this Request, for chaining
763         */
764        Request parser(Parser parser);
765
766        /**
767         * Get the current parser to use when parsing the document.
768         * @return current Parser
769         */
770        Parser parser();
771
772        /**
773         * Sets the post data character set for x-www-form-urlencoded post data
774         * @param charset character set to encode post data
775         * @return this Request, for chaining
776         */
777        Request postDataCharset(String charset);
778
779        /**
780         * Gets the post data character set for x-www-form-urlencoded post data
781         * @return character set to encode post data
782         */
783        String postDataCharset();
784
785        /**
786         Set the authenticator to use for this request.
787         See {@link Connection#auth(RequestAuthenticator) Connection.auth(authenticator)} for examples and
788         implementation notes.
789         * @param authenticator the authenticator
790         * @return this Request, for chaining.
791         * @since 1.17.1
792         */
793        default Request auth(@Nullable RequestAuthenticator authenticator)  {
794            throw new UnsupportedOperationException();
795        }
796
797        /**
798         Get the RequestAuthenticator, if any, that will be used on this request.
799         * @return the RequestAuthenticator, or {@code null} if not set
800         * @since 1.17.1
801         */
802        @Nullable
803        default RequestAuthenticator auth() {
804            throw new UnsupportedOperationException();
805        }
806    }
807
808    /**
809     * Represents a HTTP response.
810     */
811    interface Response extends Base<Response> {
812
813        /**
814         * Get the status code of the response.
815         * @return status code
816         */
817        int statusCode();
818
819        /**
820         * Get the status message of the response.
821         * @return status message
822         */
823        String statusMessage();
824
825        /**
826         * Get the character set name of the response, derived from the content-type header.
827         * @return character set name if set, <b>null</b> if not
828         */
829        @Nullable String charset();
830
831        /**
832         * Set / override the response character set. When the document body is parsed it will be with this charset.
833         * @param charset to decode body as
834         * @return this Response, for chaining
835         */
836        Response charset(String charset);
837
838        /**
839         * Get the response content type (e.g. "text/html");
840         * @return the response content type, or <b>null</b> if one was not set
841         */
842        @Nullable String contentType();
843
844        /**
845         * Read and parse the body of the response as a Document. If you intend to parse the same response multiple
846         * times, you should {@link #bufferUp()} first.
847         * @return a parsed Document
848         * @throws IOException on error
849         */
850        Document parse() throws IOException;
851
852        /**
853         * Get the body of the response as a plain string.
854         * @return body
855         */
856        String body();
857
858        /**
859         * Get the body of the response as an array of bytes.
860         * @return body bytes
861         */
862        byte[] bodyAsBytes();
863
864        /**
865         * Read the body of the response into a local buffer, so that {@link #parse()} may be called repeatedly on the
866         * same connection response. Otherwise, once the response is read, its InputStream will have been drained and
867         * may not be re-read.
868         * <p>Calling {@link #body() } or {@link #bodyAsBytes()} has the same effect.</p>
869         * @return this response, for chaining
870         * @throws UncheckedIOException if an IO exception occurs during buffering.
871         */
872        Response bufferUp();
873
874        /**
875         Get the body of the response as a (buffered) InputStream. You should close the input stream when you're done
876         with it.
877         <p>Other body methods (like bufferUp, body, parse, etc) will generally not work in conjunction with this method,
878         as it consumes the InputStream.</p>
879         <p>Any configured max size or maximum read timeout applied to the connection will not be applied to this stream,
880         unless {@link #bufferUp()} is called prior.</p>
881         <p>This method is useful for writing large responses to disk, without buffering them completely into memory
882         first.</p>
883         @return the response body input stream
884         */
885        BufferedInputStream bodyStream();
886    }
887
888    /**
889     * A Key:Value tuple(+), used for form data.
890     */
891    interface KeyVal {
892
893        /**
894         * Update the key of a keyval
895         * @param key new key
896         * @return this KeyVal, for chaining
897         */
898        KeyVal key(String key);
899
900        /**
901         * Get the key of a keyval
902         * @return the key
903         */
904        String key();
905
906        /**
907         * Update the value of a keyval
908         * @param value the new value
909         * @return this KeyVal, for chaining
910         */
911        KeyVal value(String value);
912
913        /**
914         * Get the value of a keyval
915         * @return the value
916         */
917        String value();
918
919        /**
920         * Add or update an input stream to this keyVal
921         * @param inputStream new input stream
922         * @return this KeyVal, for chaining
923         */
924        KeyVal inputStream(InputStream inputStream);
925
926        /**
927         * Get the input stream associated with this keyval, if any
928         * @return input stream if set, or null
929         */
930        @Nullable InputStream inputStream();
931
932        /**
933         * Does this keyval have an input stream?
934         * @return true if this keyval does indeed have an input stream
935         */
936        boolean hasInputStream();
937
938        /**
939         * Set the Content Type header used in the MIME body (aka mimetype) when uploading files.
940         * Only useful if {@link #inputStream(InputStream)} is set.
941         * <p>Will default to {@code application/octet-stream}.</p>
942         * @param contentType the new content type
943         * @return this KeyVal
944         */
945        KeyVal contentType(String contentType);
946
947        /**
948         * Get the current Content Type, or {@code null} if not set.
949         * @return the current Content Type.
950         */
951        @Nullable String contentType();
952    }
953}