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 -> { 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}