* To get a new Connection, use {@link org.jsoup.Jsoup#connect(String)}. * Connections contain {@link Connection.Request} and * {@link Connection.Response} objects. The request objects are reusable as * prototype requests. *
* Request configuration can be made using either the shortcut methods in * Connection (e.g. {@link #userAgent(String)}), or by methods in the * Connection.Request object directly. All request configuration must be made * before the request is executed. *
* The Connection interface is currently in beta and subject to change.
* Comments, suggestions, and bug reports are welcome.
*/
interface Connection {
/**
* GET and POST http methods.
*/
public enum Method {
GET, POST
}
/**
* Set the request URL to fetch. The protocol must be HTTP or HTTPS.
*
* @param url
* URL to connect to
* @return this Connection, for chaining
*/
public Connection url(URL url);
/**
* Set the request URL to fetch. The protocol must be HTTP or HTTPS.
*
* @param url
* URL to connect to
* @return this Connection, for chaining
*/
public Connection url(String url);
/**
* Set the request user-agent header.
*
* @param userAgent
* user-agent to use
* @return this Connection, for chaining
*/
public Connection userAgent(String userAgent);
/**
* Set the request timeouts (connect and read). If a timeout occurs, an
* IOException will be thrown. The default timeout is 3 seconds (3000
* millis). A timeout of zero is treated as an infinite timeout.
*
* @param millis
* number of milliseconds (thousandths of a second) before timing
* out connects or reads.
* @return this Connection, for chaining
*/
public Connection timeout(int millis);
/**
* Set the request referrer (aka "referer") header.
*
* @param referrer
* referrer to use
* @return this Connection, for chaining
*/
public Connection referrer(String referrer);
/**
* Configures the connection to (not) follow server redirects. By default
* this is true.
*
* @param followRedirects
* true if server redirects should be followed.
* @return this Connection, for chaining
*/
public Connection followRedirects(boolean followRedirects);
/**
* Set the request method to use, GET or POST. Default is GET.
*
* @param method
* HTTP request method
* @return this Connection, for chaining
*/
public Connection method(Method method);
/**
* Add a request data parameter. Request parameters are sent in the request
* query string for GETs, and in the request body for POSTs. A request may
* have multiple values of the same name.
*
* @param key
* data key
* @param value
* data value
* @return this Connection, for chaining
*/
public Connection data(String key, String value);
/**
* Adds all of the supplied data to the request data parameters
*
* @param data
* map of data parameters
* @return this Connection, for chaining
*/
public Connection data(Map
* Header names are case insensitive.
*
* @param name
* name of header (case insensitive)
* @return value of header, or null if not set.
* @see #hasHeader(String)
* @see #cookie(String)
*/
public String header(String name);
/**
* Set a header. This method will overwrite any existing header with the
* same case insensitive name.
*
* @param name
* Name of header
* @param value
* Value of header
* @return this, for chaining
*/
public T header(String name, String value);
/**
* Check if a header is present
*
* @param name
* name of header (case insensitive)
* @return if the header is present in this request/response
*/
public boolean hasHeader(String name);
/**
* Remove a header by name
*
* @param name
* name of header to remove (case insensitive)
* @return this, for chianing
*/
public T removeHeader(String name);
/**
* Retrieve all of the request/response headers as a map
*
* @return headers
*/
public Map
* Response objects have a simplified cookie model. Each cookie set in
* the response is added to the response object's cookie key=value map.
* The cookie's path, domain, and expiry date are ignored.
*
* @param name
* name of cookie to retrieve.
* @return value of cookie, or null if not set
*/
public String cookie(String name);
/**
* Set a cookie in this request/response.
*
* @param name
* name of cookie
* @param value
* value of cookie
* @return this, for chianing
*/
public T cookie(String name, String value);
/**
* Check if a cookie is present
*
* @param name
* name of cookie
* @return if the cookie is present in this request/response
*/
public boolean hasCookie(String name);
/**
* Remove a cookie by name
*
* @param name
* name of cookie to remove
* @return this, for chianing
*/
public T removeCookie(String name);
/**
* Retrieve all of the request/response cookies as a map
*
* @return cookies
*/
public Map
Case insensitive.
* @param seq sequence to remove from head of queue.
*/
public void consume(String seq) {
if (!matches(seq))
throw new IllegalStateException("Queue did not match expected sequence");
int len = seq.length();
if (len > remainingLength())
throw new IllegalStateException("Queue not long enough to consume sequence");
pos += len;
}
/**
* Pulls a string off the queue, up to but exclusive of the match sequence, or to the queue running out.
* @param seq String to end on (and not include in return, but leave on queue). Case sensitive.
* @return The matched data consumed from queue.
*/
public String consumeTo(String seq) {
int offset = queue.indexOf(seq, pos);
if (offset != -1) {
String consumed = queue.substring(pos, offset);
pos += consumed.length();
return consumed;
} else {
return remainder();
}
}
public String consumeToIgnoreCase(String seq) {
int start = pos;
String first = seq.substring(0, 1);
boolean canScan = first.toLowerCase().equals(first.toUpperCase()); // if first is not cased, use index of
while (!isEmpty()) {
if (matches(seq))
break;
if (canScan) {
int skip = queue.indexOf(first, pos) - pos;
if (skip == 0) // this char is the skip char, but not match, so force advance of pos
pos++;
else if (skip < 0) // no chance of finding, grab to end
pos = queue.length();
else
pos += skip;
}
else
pos++;
}
String data = queue.substring(start, pos);
return data;
}
/**
Consumes to the first sequence provided, or to the end of the queue. Leaves the terminator on the queue.
@param seq any number of terminators to consume to. Case insensitive.
@return consumed string
*/
// todo: method name. not good that consumeTo cares for case, and consume to any doesn't. And the only use for this
// is is a case sensitive time...
public String consumeToAny(String... seq) {
int start = pos;
while (!isEmpty() && !matchesAny(seq)) {
pos++;
}
String data = queue.substring(start, pos);
return data;
}
/**
* Pulls a string off the queue (like consumeTo), and then pulls off the matched string (but does not return it).
*
* If the queue runs out of characters before finding the seq, will return as much as it can (and queue will go
* isEmpty() == true).
* @param seq String to match up to, and not include in return, and to pull off queue. Case sensitive.
* @return Data matched from queue.
*/
public String chompTo(String seq) {
String data = consumeTo(seq);
matchChomp(seq);
return data;
}
public String chompToIgnoreCase(String seq) {
String data = consumeToIgnoreCase(seq); // case insensitive scan
matchChomp(seq);
return data;
}
/**
* Pulls a balanced string off the queue. E.g. if queue is "(one (two) three) four", (,) will return "one (two) three",
* and leave " four" on the queue. Unbalanced openers and closers can be escaped (with \). Those escapes will be left
* in the returned string, which is suitable for regexes (where we need to preserve the escape), but unsuitable for
* contains text strings; use unescape for that.
* @param open opener
* @param close closer
* @return data matched from the queue
*/
public String chompBalanced(char open, char close) {
StringBuilder accum = new StringBuilder();
int depth = 0;
char last = 0;
do {
if (isEmpty()) break;
Character c = consume();
if (last == 0 || last != ESC) {
if (c.equals(open))
depth++;
else if (c.equals(close))
depth--;
}
if (depth > 0 && last != 0)
accum.append(c); // don't include the outer match pair in the return
last = c;
} while (depth > 0);
return accum.toString();
}
/**
* Unescaped a \ escaped string.
* @param in backslash escaped string
* @return unescaped string
*/
public static String unescape(String in) {
StringBuilder out = new StringBuilder();
char last = 0;
for (char c : in.toCharArray()) {
if (c == ESC) {
if (last != 0 && last == ESC)
out.append(c);
}
else
out.append(c);
last = c;
}
return out.toString();
}
/**
* Pulls the next run of whitespace characters of the queue.
*/
public boolean consumeWhitespace() {
boolean seen = false;
while (matchesWhitespace()) {
pos++;
seen = true;
}
return seen;
}
/**
* Retrieves the next run of word type (letter or digit) off the queue.
* @return String of word characters from queue, or empty string if none.
*/
public String consumeWord() {
int start = pos;
while (matchesWord())
pos++;
return queue.substring(start, pos);
}
/**
* Consume an tag name off the queue (word or :, _, -)
*
* @return tag name
*/
public String consumeTagName() {
int start = pos;
while (!isEmpty() && (matchesWord() || matchesAny(':', '_', '-')))
pos++;
return queue.substring(start, pos);
}
/**
* Consume a CSS element selector (tag name, but | instead of : for namespaces, to not conflict with :pseudo selects).
*
* @return tag name
*/
public String consumeElementSelector() {
int start = pos;
while (!isEmpty() && (matchesWord() || matchesAny('|', '_', '-')))
pos++;
return queue.substring(start, pos);
}
/**
Consume a CSS identifier (ID or class) off the queue (letter, digit, -, _)
http://www.w3.org/TR/CSS2/syndata.html#value-def-identifier
@return identifier
*/
public String consumeCssIdentifier() {
int start = pos;
while (!isEmpty() && (matchesWord() || matchesAny('-', '_')))
pos++;
return queue.substring(start, pos);
}
/**
Consume an attribute key off the queue (letter, digit, -, _, :")
@return attribute key
*/
public String consumeAttributeKey() {
int start = pos;
while (!isEmpty() && (matchesWord() || matchesAny('-', '_', ':')))
pos++;
return queue.substring(start, pos);
}
/**
Consume and return whatever is left on the queue.
@return remained of queue.
*/
public String remainder() {
StringBuilder accum = new StringBuilder();
while (!isEmpty()) {
accum.append(consume());
}
return accum.toString();
}
public String toString() {
return queue.substring(pos);
}
}
.data("name", "jsoup", "language", "Java", "language", "English");
* creates a query string like:
* ?name=jsoup&language=Java&language=English
*
* @param keyvals
* a set of key value pairs.
* @return this Connection, for chaining
*/
public Connection data(String... keyvals);
/**
* Set a request header.
*
* @param name
* header name
* @param value
* header value
* @return this Connection, for chaining
* @see org.jsoup.Connection.Request#headers()
*/
public Connection header(String name, String value);
/**
* Set a cookie to be sent in the request
*
* @param name
* name of cookie
* @param value
* value of cookie
* @return this Connection, for chaining
*/
public Connection cookie(String name, String value);
/**
* Execute the request.
*
* @return a response object
* @throws IOException
* on error
*/
public Response execute() throws IOException;
/**
* Get the request object associatated with this connection
*
* @return request
*/
public Request request();
/**
* Set the connection's request
*
* @param request
* new request object
* @return this Connection, for chaining
*/
public Connection request(Request request);
/**
* Get the response, once the request has been executed
*
* @return response
*/
public Response response();
/**
* Set the conenction's response
*
* @param response
* new response
* @return this Connection, for chaining
*/
public Connection response(Response response);
/**
* Common methods for Requests and Responses
*
* @param