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