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