| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package java.net; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.util.Arrays; |
| import libcore.net.http.HttpEngine; |
| |
| /** |
| * An {@link URLConnection} for HTTP (<a |
| * href="http://tools.ietf.org/html/rfc2616">RFC 2616</a>) used to send and |
| * receive data over the web. Data may be of any type and length. This class may |
| * be used to send and receive streaming data whose length is not known in |
| * advance. |
| * |
| * <p>Uses of this class follow a pattern: |
| * <ol> |
| * <li>Obtain a new {@code HttpURLConnection} by calling {@link |
| * URL#openConnection() URL.openConnection()} and casting the result to |
| * {@code HttpURLConnection}. |
| * <li>Prepare the request. The primary property of a request is its URI. |
| * Request headers may also include metadata such as credentials, preferred |
| * content types, and session cookies. |
| * <li>Optionally upload a request body. Instances must be configured with |
| * {@link #setDoOutput(boolean) setDoOutput(true)} if they include a |
| * request body. Transmit data by writing to the stream returned by {@link |
| * #getOutputStream()}. |
| * <li>Read the response. Response headers typically include metadata such as |
| * the response body's content type and length, modified dates and session |
| * cookies. The response body may be read from the stream returned by {@link |
| * #getInputStream()}. If the response has no body, that method returns an |
| * empty stream. |
| * <li>Disconnect. Once the response body has been read, the {@code |
| * HttpURLConnection} should be closed by calling {@link #disconnect()}. |
| * Disconnecting releases the resources held by a connection so they may |
| * be closed or reused. |
| * </ol> |
| * |
| * <p>For example, to retrieve the webpage at {@code http://www.android.com/}: |
| * <pre> {@code |
| * URL url = new URL("http://www.android.com/"); |
| * HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); |
| * try { |
| * InputStream in = new BufferedInputStream(urlConnection.getInputStream()); |
| * readStream(in); |
| * } finally { |
| * urlConnection.disconnect(); |
| * } |
| * }</pre> |
| * |
| * <h3>Secure Communication with HTTPS</h3> |
| * Calling {@link URL#openConnection()} on a URL with the "https" |
| * scheme will return an {@code HttpsURLConnection}, which allows for |
| * overriding the default {@link javax.net.ssl.HostnameVerifier |
| * HostnameVerifier} and {@link javax.net.ssl.SSLSocketFactory |
| * SSLSocketFactory}. An application-supplied {@code SSLSocketFactory} |
| * created from an {@link javax.net.ssl.SSLContext SSLContext} can |
| * provide a custom {@link javax.net.ssl.X509TrustManager |
| * X509TrustManager} for verifying certificate chains and a custom |
| * {@link javax.net.ssl.X509KeyManager X509KeyManager} for supplying |
| * client certificates. See {@link javax.net.ssl.HttpsURLConnection |
| * HttpsURLConnection} for more details. |
| * |
| * <h3>Response Handling</h3> |
| * {@code HttpURLConnection} will follow up to five HTTP redirects. It will |
| * follow redirects from one origin server to another. This implementation |
| * doesn't follow redirects from HTTPS to HTTP or vice versa. |
| * |
| * <p>If the HTTP response indicates that an error occurred, {@link |
| * #getInputStream()} will throw an {@link IOException}. Use {@link |
| * #getErrorStream()} to read the error response. The headers can be read in |
| * the normal way using {@link #getHeaderFields()}, |
| * |
| * <h3>Posting Content</h3> |
| * To upload data to a web server, configure the connection for output using |
| * {@link #setDoOutput(boolean) setDoOutput(true)}. |
| * |
| * <p>For best performance, you should call either {@link |
| * #setFixedLengthStreamingMode(int)} when the body length is known in advance, |
| * or {@link #setChunkedStreamingMode(int)} when it is not. Otherwise {@code |
| * HttpURLConnection} will be forced to buffer the complete request body in |
| * memory before it is transmitted, wasting (and possibly exhausting) heap and |
| * increasing latency. |
| * |
| * <p>For example, to perform an upload: <pre> {@code |
| * HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); |
| * try { |
| * urlConnection.setDoOutput(true); |
| * urlConnection.setChunkedStreamingMode(0); |
| * |
| * OutputStream out = new BufferedOutputStream(urlConnection.getOutputStream()); |
| * writeStream(out); |
| * |
| * InputStream in = new BufferedInputStream(urlConnection.getInputStream()); |
| * readStream(in); |
| * } finally { |
| * urlConnection.disconnect(); |
| * } |
| * }</pre> |
| * |
| * <h3>Performance</h3> |
| * The input and output streams returned by this class are <strong>not |
| * buffered</strong>. Most callers should wrap the returned streams with {@link |
| * java.io.BufferedInputStream BufferedInputStream} or {@link |
| * java.io.BufferedOutputStream BufferedOutputStream}. Callers that do only bulk |
| * reads or writes may omit buffering. |
| * |
| * <p>When transferring large amounts of data to or from a server, use streams |
| * to limit how much data is in memory at once. Unless you need the entire |
| * body to be in memory at once, process it as a stream (rather than storing |
| * the complete body as a single byte array or string). |
| * |
| * <p>To reduce latency, this class may reuse the same underlying {@code Socket} |
| * for multiple request/response pairs. As a result, HTTP connections may be |
| * held open longer than necessary. Calls to {@link #disconnect()} may return |
| * the socket to a pool of connected sockets. This behavior can be disabled by |
| * setting the {@code http.keepAlive} system property to {@code false} before |
| * issuing any HTTP requests. The {@code http.maxConnections} property may be |
| * used to control how many idle connections to each server will be held. |
| * |
| * <p>By default, this implementation of {@code HttpURLConnection} requests that |
| * servers use gzip compression. Since {@link #getContentLength()} returns the |
| * number of bytes transmitted, you cannot use that method to predict how many |
| * bytes can be read from {@link #getInputStream()}. Instead, read that stream |
| * until it is exhausted: when {@link InputStream#read} returns -1. Gzip |
| * compression can be disabled by setting the acceptable encodings in the |
| * request header: <pre> {@code |
| * urlConnection.setRequestProperty("Accept-Encoding", "identity"); |
| * }</pre> |
| * |
| * <h3>Handling Network Sign-On</h3> |
| * Some Wi-Fi networks block Internet access until the user clicks through a |
| * sign-on page. Such sign-on pages are typically presented by using HTTP |
| * redirects. You can use {@link #getURL()} to test if your connection has been |
| * unexpectedly redirected. This check is not valid until <strong>after</strong> |
| * the response headers have been received, which you can trigger by calling |
| * {@link #getHeaderFields()} or {@link #getInputStream()}. For example, to |
| * check that a response was not redirected to an unexpected host: |
| * <pre> {@code |
| * HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); |
| * try { |
| * InputStream in = new BufferedInputStream(urlConnection.getInputStream()); |
| * if (!url.getHost().equals(urlConnection.getURL().getHost())) { |
| * // we were redirected! Kick the user out to the browser to sign on? |
| * } |
| * ... |
| * } finally { |
| * urlConnection.disconnect(); |
| * } |
| * }</pre> |
| * |
| * <h3>HTTP Authentication</h3> |
| * {@code HttpURLConnection} supports <a |
| * href="http://www.ietf.org/rfc/rfc2617">HTTP basic authentication</a>. Use |
| * {@link Authenticator} to set the VM-wide authentication handler: |
| * <pre> {@code |
| * Authenticator.setDefault(new Authenticator() { |
| * protected PasswordAuthentication getPasswordAuthentication() { |
| * return new PasswordAuthentication(username, password.toCharArray()); |
| * } |
| * }); |
| * }</pre> |
| * Unless paired with HTTPS, this is <strong>not</strong> a secure mechanism for |
| * user authentication. In particular, the username, password, request and |
| * response are all transmitted over the network without encryption. |
| * |
| * <h3>Sessions with Cookies</h3> |
| * To establish and maintain a potentially long-lived session between client |
| * and server, {@code HttpURLConnection} includes an extensible cookie manager. |
| * Enable VM-wide cookie management using {@link CookieHandler} and {@link |
| * CookieManager}: <pre> {@code |
| * CookieManager cookieManager = new CookieManager(); |
| * CookieHandler.setDefault(cookieManager); |
| * }</pre> |
| * By default, {@code CookieManager} accepts cookies from the <a |
| * href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec1.html">origin |
| * server</a> only. Two other policies are included: {@link |
| * CookiePolicy#ACCEPT_ALL} and {@link CookiePolicy#ACCEPT_NONE}. Implement |
| * {@link CookiePolicy} to define a custom policy. |
| * |
| * <p>The default {@code CookieManager} keeps all accepted cookies in memory. It |
| * will forget these cookies when the VM exits. Implement {@link CookieStore} to |
| * define a custom cookie store. |
| * |
| * <p>In addition to the cookies set by HTTP responses, you may set cookies |
| * programmatically. To be included in HTTP request headers, cookies must have |
| * the domain and path properties set. |
| * |
| * <p>By default, new instances of {@code HttpCookie} work only with servers |
| * that support <a href="http://www.ietf.org/rfc/rfc2965.txt">RFC 2965</a> |
| * cookies. Many web servers support only the older specification, <a |
| * href="http://www.ietf.org/rfc/rfc2109.txt">RFC 2109</a>. For compatibility |
| * with the most web servers, set the cookie version to 0. |
| * |
| * <p>For example, to receive {@code www.twitter.com} in French: <pre> {@code |
| * HttpCookie cookie = new HttpCookie("lang", "fr"); |
| * cookie.setDomain("twitter.com"); |
| * cookie.setPath("/"); |
| * cookie.setVersion(0); |
| * cookieManager.getCookieStore().add(new URI("http://twitter.com/"), cookie); |
| * }</pre> |
| * |
| * <h3>HTTP Methods</h3> |
| * <p>{@code HttpURLConnection} uses the {@code GET} method by default. It will |
| * use {@code POST} if {@link #setDoOutput setDoOutput(true)} has been called. |
| * Other HTTP methods ({@code OPTIONS}, {@code HEAD}, {@code PUT}, {@code |
| * DELETE} and {@code TRACE}) can be used with {@link #setRequestMethod}. |
| * |
| * <h3>Proxies</h3> |
| * By default, this class will connect directly to the <a |
| * href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec1.html">origin |
| * server</a>. It can also connect via an {@link Proxy.Type#HTTP HTTP} or {@link |
| * Proxy.Type#SOCKS SOCKS} proxy. To use a proxy, use {@link |
| * URL#openConnection(Proxy) URL.openConnection(Proxy)} when creating the |
| * connection. |
| * |
| * <h3>IPv6 Support</h3> |
| * <p>This class includes transparent support for IPv6. For hosts with both IPv4 |
| * and IPv6 addresses, it will attempt to connect to each of a host's addresses |
| * until a connection is established. |
| * |
| * <h3>Response Caching</h3> |
| * Android 4.0 (Ice Cream Sandwich) includes a response cache. See {@code |
| * android.net.http.HttpResponseCache} for instructions on enabling HTTP caching |
| * in your application. |
| * |
| * <h3>Avoiding Bugs In Earlier Releases</h3> |
| * Prior to Android 2.2 (Froyo), this class had some frustrating bugs. In |
| * particular, calling {@code close()} on a readable {@code InputStream} could |
| * <a href="http://code.google.com/p/android/issues/detail?id=2939">poison the |
| * connection pool</a>. Work around this by disabling connection pooling: |
| * <pre> {@code |
| * private void disableConnectionReuseIfNecessary() { |
| * // Work around pre-Froyo bugs in HTTP connection reuse. |
| * if (Integer.parseInt(Build.VERSION.SDK) < Build.VERSION_CODES.FROYO) { |
| * System.setProperty("http.keepAlive", "false"); |
| * } |
| * }}</pre> |
| * |
| * <p>Each instance of {@code HttpURLConnection} may be used for one |
| * request/response pair. Instances of this class are not thread safe. |
| */ |
| public abstract class HttpURLConnection extends URLConnection { |
| |
| /** |
| * The subset of HTTP methods that the user may select via {@link |
| * #setRequestMethod(String)}. |
| */ |
| private static final String[] PERMITTED_USER_METHODS = { |
| HttpEngine.OPTIONS, |
| HttpEngine.GET, |
| HttpEngine.HEAD, |
| HttpEngine.POST, |
| HttpEngine.PUT, |
| HttpEngine.DELETE, |
| HttpEngine.TRACE |
| // Note: we don't allow users to specify "CONNECT" |
| }; |
| |
| /** |
| * The HTTP request method of this {@code HttpURLConnection}. The default |
| * value is {@code "GET"}. |
| */ |
| protected String method = HttpEngine.GET; |
| |
| /** |
| * The status code of the response obtained from the HTTP request. The |
| * default value is {@code -1}. |
| * <p> |
| * <li>1xx: Informational</li> |
| * <li>2xx: Success</li> |
| * <li>3xx: Relocation/Redirection</li> |
| * <li>4xx: Client Error</li> |
| * <li>5xx: Server Error</li> |
| */ |
| protected int responseCode = -1; |
| |
| /** |
| * The HTTP response message which corresponds to the response code. |
| */ |
| protected String responseMessage; |
| |
| /** |
| * Flag to define whether the protocol will automatically follow redirects |
| * or not. The default value is {@code true}. |
| */ |
| protected boolean instanceFollowRedirects = followRedirects; |
| |
| private static boolean followRedirects = true; |
| |
| /** |
| * If the HTTP chunked encoding is enabled this parameter defines the |
| * chunk-length. Default value is {@code -1} that means the chunked encoding |
| * mode is disabled. |
| */ |
| protected int chunkLength = -1; |
| |
| /** |
| * If using HTTP fixed-length streaming mode this parameter defines the |
| * fixed length of content. Default value is {@code -1} that means the |
| * fixed-length streaming mode is disabled. |
| */ |
| protected int fixedContentLength = -1; |
| |
| // 2XX: generally "OK" |
| // 3XX: relocation/redirect |
| // 4XX: client error |
| // 5XX: server error |
| /** |
| * Numeric status code, 202: Accepted |
| */ |
| public static final int HTTP_ACCEPTED = 202; |
| |
| /** |
| * Numeric status code, 502: Bad Gateway |
| */ |
| public static final int HTTP_BAD_GATEWAY = 502; |
| |
| /** |
| * Numeric status code, 405: Bad Method |
| */ |
| public static final int HTTP_BAD_METHOD = 405; |
| |
| /** |
| * Numeric status code, 400: Bad Request |
| */ |
| public static final int HTTP_BAD_REQUEST = 400; |
| |
| /** |
| * Numeric status code, 408: Client Timeout |
| */ |
| public static final int HTTP_CLIENT_TIMEOUT = 408; |
| |
| /** |
| * Numeric status code, 409: Conflict |
| */ |
| public static final int HTTP_CONFLICT = 409; |
| |
| /** |
| * Numeric status code, 201: Created |
| */ |
| public static final int HTTP_CREATED = 201; |
| |
| /** |
| * Numeric status code, 413: Entity too large |
| */ |
| public static final int HTTP_ENTITY_TOO_LARGE = 413; |
| |
| /** |
| * Numeric status code, 403: Forbidden |
| */ |
| public static final int HTTP_FORBIDDEN = 403; |
| |
| /** |
| * Numeric status code, 504: Gateway timeout |
| */ |
| public static final int HTTP_GATEWAY_TIMEOUT = 504; |
| |
| /** |
| * Numeric status code, 410: Gone |
| */ |
| public static final int HTTP_GONE = 410; |
| |
| /** |
| * Numeric status code, 500: Internal error |
| */ |
| public static final int HTTP_INTERNAL_ERROR = 500; |
| |
| /** |
| * Numeric status code, 411: Length required |
| */ |
| public static final int HTTP_LENGTH_REQUIRED = 411; |
| |
| /** |
| * Numeric status code, 301 Moved permanently |
| */ |
| public static final int HTTP_MOVED_PERM = 301; |
| |
| /** |
| * Numeric status code, 302: Moved temporarily |
| */ |
| public static final int HTTP_MOVED_TEMP = 302; |
| |
| /** |
| * Numeric status code, 300: Multiple choices |
| */ |
| public static final int HTTP_MULT_CHOICE = 300; |
| |
| /** |
| * Numeric status code, 204: No content |
| */ |
| public static final int HTTP_NO_CONTENT = 204; |
| |
| /** |
| * Numeric status code, 406: Not acceptable |
| */ |
| public static final int HTTP_NOT_ACCEPTABLE = 406; |
| |
| /** |
| * Numeric status code, 203: Not authoritative |
| */ |
| public static final int HTTP_NOT_AUTHORITATIVE = 203; |
| |
| /** |
| * Numeric status code, 404: Not found |
| */ |
| public static final int HTTP_NOT_FOUND = 404; |
| |
| /** |
| * Numeric status code, 501: Not implemented |
| */ |
| public static final int HTTP_NOT_IMPLEMENTED = 501; |
| |
| /** |
| * Numeric status code, 304: Not modified |
| */ |
| public static final int HTTP_NOT_MODIFIED = 304; |
| |
| /** |
| * Numeric status code, 200: OK |
| */ |
| public static final int HTTP_OK = 200; |
| |
| /** |
| * Numeric status code, 206: Partial |
| */ |
| public static final int HTTP_PARTIAL = 206; |
| |
| /** |
| * Numeric status code, 402: Payment required |
| */ |
| public static final int HTTP_PAYMENT_REQUIRED = 402; |
| |
| /** |
| * Numeric status code, 412: Precondition failed |
| */ |
| public static final int HTTP_PRECON_FAILED = 412; |
| |
| /** |
| * Numeric status code, 407: Proxy authentication required |
| */ |
| public static final int HTTP_PROXY_AUTH = 407; |
| |
| /** |
| * Numeric status code, 414: Request too long |
| */ |
| public static final int HTTP_REQ_TOO_LONG = 414; |
| |
| /** |
| * Numeric status code, 205: Reset |
| */ |
| public static final int HTTP_RESET = 205; |
| |
| /** |
| * Numeric status code, 303: See other |
| */ |
| public static final int HTTP_SEE_OTHER = 303; |
| |
| /** |
| * Numeric status code, 500: Internal error |
| * |
| * @deprecated Use {@link #HTTP_INTERNAL_ERROR} |
| */ |
| @Deprecated |
| public static final int HTTP_SERVER_ERROR = 500; |
| |
| /** |
| * Numeric status code, 305: Use proxy. |
| * |
| * <p>Like Firefox and Chrome, this class doesn't honor this response code. |
| * Other implementations respond to this status code by retrying the request |
| * using the HTTP proxy named by the response's Location header field. |
| */ |
| public static final int HTTP_USE_PROXY = 305; |
| |
| /** |
| * Numeric status code, 401: Unauthorized |
| */ |
| public static final int HTTP_UNAUTHORIZED = 401; |
| |
| /** |
| * Numeric status code, 415: Unsupported type |
| */ |
| public static final int HTTP_UNSUPPORTED_TYPE = 415; |
| |
| /** |
| * Numeric status code, 503: Unavailable |
| */ |
| public static final int HTTP_UNAVAILABLE = 503; |
| |
| /** |
| * Numeric status code, 505: Version not supported |
| */ |
| public static final int HTTP_VERSION = 505; |
| |
| /** |
| * Constructs a new {@code HttpURLConnection} instance pointing to the |
| * resource specified by the {@code url}. |
| * |
| * @param url |
| * the URL of this connection. |
| * @see URL |
| * @see URLConnection |
| */ |
| protected HttpURLConnection(URL url) { |
| super(url); |
| } |
| |
| /** |
| * Releases this connection so that its resources may be either reused or |
| * closed. |
| * |
| * <p>Unlike other Java implementations, this will not necessarily close |
| * socket connections that can be reused. You can disable all connection |
| * reuse by setting the {@code http.keepAlive} system property to {@code |
| * false} before issuing any HTTP requests. |
| */ |
| public abstract void disconnect(); |
| |
| /** |
| * Returns an input stream from the server in the case of an error such as |
| * the requested file has not been found on the remote server. This stream |
| * can be used to read the data the server will send back. |
| * |
| * @return the error input stream returned by the server. |
| */ |
| public InputStream getErrorStream() { |
| return null; |
| } |
| |
| /** |
| * Returns the value of {@code followRedirects} which indicates if this |
| * connection follows a different URL redirected by the server. It is |
| * enabled by default. |
| * |
| * @return the value of the flag. |
| * @see #setFollowRedirects |
| */ |
| public static boolean getFollowRedirects() { |
| return followRedirects; |
| } |
| |
| /** |
| * Returns the permission object (in this case {@code SocketPermission}) |
| * with the host and the port number as the target name and {@code |
| * "resolve, connect"} as the action list. If the port number of this URL |
| * instance is lower than {@code 0} the port will be set to {@code 80}. |
| * |
| * @return the permission object required for this connection. |
| * @throws IOException |
| * if an IO exception occurs during the creation of the |
| * permission object. |
| */ |
| @Override |
| public java.security.Permission getPermission() throws IOException { |
| int port = url.getPort(); |
| if (port < 0) { |
| port = 80; |
| } |
| return new SocketPermission(url.getHost() + ":" + port, |
| "connect, resolve"); |
| } |
| |
| /** |
| * Returns the request method which will be used to make the request to the |
| * remote HTTP server. All possible methods of this HTTP implementation is |
| * listed in the class definition. |
| * |
| * @return the request method string. |
| * @see #method |
| * @see #setRequestMethod |
| */ |
| public String getRequestMethod() { |
| return method; |
| } |
| |
| /** |
| * Returns the response code returned by the remote HTTP server. |
| * |
| * @return the response code, -1 if no valid response code. |
| * @throws IOException |
| * if there is an IO error during the retrieval. |
| * @see #getResponseMessage |
| */ |
| public int getResponseCode() throws IOException { |
| // Call getInputStream() first since getHeaderField() doesn't return |
| // exceptions |
| getInputStream(); |
| String response = getHeaderField(0); |
| if (response == null) { |
| return -1; |
| } |
| response = response.trim(); |
| int mark = response.indexOf(" ") + 1; |
| if (mark == 0) { |
| return -1; |
| } |
| int last = mark + 3; |
| if (last > response.length()) { |
| last = response.length(); |
| } |
| responseCode = Integer.parseInt(response.substring(mark, last)); |
| if (last + 1 <= response.length()) { |
| responseMessage = response.substring(last + 1); |
| } |
| return responseCode; |
| } |
| |
| /** |
| * Returns the response message returned by the remote HTTP server. |
| * |
| * @return the response message. {@code null} if no such response exists. |
| * @throws IOException |
| * if there is an error during the retrieval. |
| * @see #getResponseCode() |
| */ |
| public String getResponseMessage() throws IOException { |
| if (responseMessage != null) { |
| return responseMessage; |
| } |
| getResponseCode(); |
| return responseMessage; |
| } |
| |
| /** |
| * Sets the flag of whether this connection will follow redirects returned |
| * by the remote server. |
| * |
| * @param auto |
| * the value to enable or disable this option. |
| */ |
| public static void setFollowRedirects(boolean auto) { |
| followRedirects = auto; |
| } |
| |
| /** |
| * Sets the request command which will be sent to the remote HTTP server. |
| * This method can only be called before the connection is made. |
| * |
| * @param method |
| * the string representing the method to be used. |
| * @throws ProtocolException |
| * if this is called after connected, or the method is not |
| * supported by this HTTP implementation. |
| * @see #getRequestMethod() |
| * @see #method |
| */ |
| public void setRequestMethod(String method) throws ProtocolException { |
| if (connected) { |
| throw new ProtocolException("Connection already established"); |
| } |
| for (String permittedUserMethod : PERMITTED_USER_METHODS) { |
| if (permittedUserMethod.equals(method)) { |
| // if there is a supported method that matches the desired |
| // method, then set the current method and return |
| this.method = permittedUserMethod; |
| return; |
| } |
| } |
| // if none matches, then throw ProtocolException |
| throw new ProtocolException("Unknown method '" + method + "'; must be one of " + |
| Arrays.toString(PERMITTED_USER_METHODS)); |
| } |
| |
| /** |
| * Returns whether this connection uses a proxy server or not. |
| * |
| * @return {@code true} if this connection passes a proxy server, false |
| * otherwise. |
| */ |
| public abstract boolean usingProxy(); |
| |
| /** |
| * Returns the encoding used to transmit the response body over the network. |
| * This is null or "identity" if the content was not encoded, or "gzip" if |
| * the body was gzip compressed. Most callers will be more interested in the |
| * {@link #getContentType() content type}, which may also include the |
| * content's character encoding. |
| */ |
| @Override public String getContentEncoding() { |
| return super.getContentEncoding(); // overridden for Javadoc only |
| } |
| |
| /** |
| * Returns whether this connection follows redirects. |
| * |
| * @return {@code true} if this connection follows redirects, false |
| * otherwise. |
| */ |
| public boolean getInstanceFollowRedirects() { |
| return instanceFollowRedirects; |
| } |
| |
| /** |
| * Sets whether this connection follows redirects. |
| * |
| * @param followRedirects |
| * {@code true} if this connection will follows redirects, false |
| * otherwise. |
| */ |
| public void setInstanceFollowRedirects(boolean followRedirects) { |
| instanceFollowRedirects = followRedirects; |
| } |
| |
| /** |
| * Returns the date value in milliseconds since {@code 01.01.1970, 00:00h} |
| * corresponding to the header field {@code field}. The {@code defaultValue} |
| * will be returned if no such field can be found in the response header. |
| * |
| * @param field |
| * the header field name. |
| * @param defaultValue |
| * the default value to use if the specified header field wont be |
| * found. |
| * @return the header field represented in milliseconds since January 1, |
| * 1970 GMT. |
| */ |
| @Override |
| public long getHeaderFieldDate(String field, long defaultValue) { |
| return super.getHeaderFieldDate(field, defaultValue); |
| } |
| |
| /** |
| * If the length of a HTTP request body is known ahead, sets fixed length to |
| * enable streaming without buffering. Sets after connection will cause an |
| * exception. |
| * |
| * @see #setChunkedStreamingMode |
| * @param contentLength |
| * the fixed length of the HTTP request body. |
| * @throws IllegalStateException |
| * if already connected or another mode already set. |
| * @throws IllegalArgumentException |
| * if {@code contentLength} is less than zero. |
| */ |
| public void setFixedLengthStreamingMode(int contentLength) { |
| if (super.connected) { |
| throw new IllegalStateException("Already connected"); |
| } |
| if (chunkLength > 0) { |
| throw new IllegalStateException("Already in chunked mode"); |
| } |
| if (contentLength < 0) { |
| throw new IllegalArgumentException("contentLength < 0"); |
| } |
| this.fixedContentLength = contentLength; |
| } |
| |
| /** |
| * Stream a request body whose length is not known in advance. Old HTTP/1.0 |
| * only servers may not support this mode. |
| * |
| * <p>When HTTP chunked encoding is used, the stream is divided into |
| * chunks, each prefixed with a header containing the chunk's size. Setting |
| * a large chunk length requires a large internal buffer, potentially |
| * wasting memory. Setting a small chunk length increases the number of |
| * bytes that must be transmitted because of the header on every chunk. |
| * Most caller should use {@code 0} to get the system default. |
| * |
| * @see #setFixedLengthStreamingMode |
| * @param chunkLength the length to use, or {@code 0} for the default chunk |
| * length. |
| * @throws IllegalStateException if already connected or another mode |
| * already set. |
| */ |
| public void setChunkedStreamingMode(int chunkLength) { |
| if (super.connected) { |
| throw new IllegalStateException("Already connected"); |
| } |
| if (fixedContentLength >= 0) { |
| throw new IllegalStateException("Already in fixed-length mode"); |
| } |
| if (chunkLength <= 0) { |
| this.chunkLength = HttpEngine.DEFAULT_CHUNK_LENGTH; |
| } else { |
| this.chunkLength = chunkLength; |
| } |
| } |
| } |