Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/net/HttpURLConnection.java
38829 views
/*1* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.net;2627import java.io.InputStream;28import java.io.IOException;29import java.security.Permission;30import java.util.Date;3132/**33* A URLConnection with support for HTTP-specific features. See34* <A HREF="http://www.w3.org/pub/WWW/Protocols/"> the spec </A> for35* details.36* <p>37*38* Each HttpURLConnection instance is used to make a single request39* but the underlying network connection to the HTTP server may be40* transparently shared by other instances. Calling the close() methods41* on the InputStream or OutputStream of an HttpURLConnection42* after a request may free network resources associated with this43* instance but has no effect on any shared persistent connection.44* Calling the disconnect() method may close the underlying socket45* if a persistent connection is otherwise idle at that time.46*47* <P>The HTTP protocol handler has a few settings that can be accessed through48* System Properties. This covers49* <a href="doc-files/net-properties.html#Proxies">Proxy settings</a> as well as50* <a href="doc-files/net-properties.html#MiscHTTP"> various other settings</a>.51* </P>52* <p>53* <b>Security permissions</b>54* <p>55* If a security manager is installed, and if a method is called which results in an56* attempt to open a connection, the caller must possess either:-57* <ul><li>a "connect" {@link SocketPermission} to the host/port combination of the58* destination URL or</li>59* <li>a {@link URLPermission} that permits this request.</li>60* </ul><p>61* If automatic redirection is enabled, and this request is redirected to another62* destination, then the caller must also have permission to connect to the63* redirected host/URL.64*65* @see java.net.HttpURLConnection#disconnect()66* @since JDK1.167*/68abstract public class HttpURLConnection extends URLConnection {69/* instance variables */7071/**72* The HTTP method (GET,POST,PUT,etc.).73*/74protected String method = "GET";7576/**77* The chunk-length when using chunked encoding streaming mode for output.78* A value of {@code -1} means chunked encoding is disabled for output.79* @since 1.580*/81protected int chunkLength = -1;8283/**84* The fixed content-length when using fixed-length streaming mode.85* A value of {@code -1} means fixed-length streaming mode is disabled86* for output.87*88* <P> <B>NOTE:</B> {@link #fixedContentLengthLong} is recommended instead89* of this field, as it allows larger content lengths to be set.90*91* @since 1.592*/93protected int fixedContentLength = -1;9495/**96* The fixed content-length when using fixed-length streaming mode.97* A value of {@code -1} means fixed-length streaming mode is disabled98* for output.99*100* @since 1.7101*/102protected long fixedContentLengthLong = -1;103104/**105* Returns the key for the {@code n}<sup>th</sup> header field.106* Some implementations may treat the {@code 0}<sup>th</sup>107* header field as special, i.e. as the status line returned by the HTTP108* server. In this case, {@link #getHeaderField(int) getHeaderField(0)} returns the status109* line, but {@code getHeaderFieldKey(0)} returns null.110*111* @param n an index, where {@code n >=0}.112* @return the key for the {@code n}<sup>th</sup> header field,113* or {@code null} if the key does not exist.114*/115public String getHeaderFieldKey (int n) {116return null;117}118119/**120* This method is used to enable streaming of a HTTP request body121* without internal buffering, when the content length is known in122* advance.123* <p>124* An exception will be thrown if the application125* attempts to write more data than the indicated126* content-length, or if the application closes the OutputStream127* before writing the indicated amount.128* <p>129* When output streaming is enabled, authentication130* and redirection cannot be handled automatically.131* A HttpRetryException will be thrown when reading132* the response if authentication or redirection are required.133* This exception can be queried for the details of the error.134* <p>135* This method must be called before the URLConnection is connected.136* <p>137* <B>NOTE:</B> {@link #setFixedLengthStreamingMode(long)} is recommended138* instead of this method as it allows larger content lengths to be set.139*140* @param contentLength The number of bytes which will be written141* to the OutputStream.142*143* @throws IllegalStateException if URLConnection is already connected144* or if a different streaming mode is already enabled.145*146* @throws IllegalArgumentException if a content length less than147* zero is specified.148*149* @see #setChunkedStreamingMode(int)150* @since 1.5151*/152public void setFixedLengthStreamingMode (int contentLength) {153if (connected) {154throw new IllegalStateException ("Already connected");155}156if (chunkLength != -1) {157throw new IllegalStateException ("Chunked encoding streaming mode set");158}159if (contentLength < 0) {160throw new IllegalArgumentException ("invalid content length");161}162fixedContentLength = contentLength;163}164165/**166* This method is used to enable streaming of a HTTP request body167* without internal buffering, when the content length is known in168* advance.169*170* <P> An exception will be thrown if the application attempts to write171* more data than the indicated content-length, or if the application172* closes the OutputStream before writing the indicated amount.173*174* <P> When output streaming is enabled, authentication and redirection175* cannot be handled automatically. A {@linkplain HttpRetryException} will176* be thrown when reading the response if authentication or redirection177* are required. This exception can be queried for the details of the178* error.179*180* <P> This method must be called before the URLConnection is connected.181*182* <P> The content length set by invoking this method takes precedence183* over any value set by {@link #setFixedLengthStreamingMode(int)}.184*185* @param contentLength186* The number of bytes which will be written to the OutputStream.187*188* @throws IllegalStateException189* if URLConnection is already connected or if a different190* streaming mode is already enabled.191*192* @throws IllegalArgumentException193* if a content length less than zero is specified.194*195* @since 1.7196*/197public void setFixedLengthStreamingMode(long contentLength) {198if (connected) {199throw new IllegalStateException("Already connected");200}201if (chunkLength != -1) {202throw new IllegalStateException(203"Chunked encoding streaming mode set");204}205if (contentLength < 0) {206throw new IllegalArgumentException("invalid content length");207}208fixedContentLengthLong = contentLength;209}210211/* Default chunk size (including chunk header) if not specified;212* we want to keep this in sync with the one defined in213* sun.net.www.http.ChunkedOutputStream214*/215private static final int DEFAULT_CHUNK_SIZE = 4096;216217/**218* This method is used to enable streaming of a HTTP request body219* without internal buffering, when the content length is <b>not</b>220* known in advance. In this mode, chunked transfer encoding221* is used to send the request body. Note, not all HTTP servers222* support this mode.223* <p>224* When output streaming is enabled, authentication225* and redirection cannot be handled automatically.226* A HttpRetryException will be thrown when reading227* the response if authentication or redirection are required.228* This exception can be queried for the details of the error.229* <p>230* This method must be called before the URLConnection is connected.231*232* @param chunklen The number of bytes to write in each chunk.233* If chunklen is less than or equal to zero, a default234* value will be used.235*236* @throws IllegalStateException if URLConnection is already connected237* or if a different streaming mode is already enabled.238*239* @see #setFixedLengthStreamingMode(int)240* @since 1.5241*/242public void setChunkedStreamingMode (int chunklen) {243if (connected) {244throw new IllegalStateException ("Can't set streaming mode: already connected");245}246if (fixedContentLength != -1 || fixedContentLengthLong != -1) {247throw new IllegalStateException ("Fixed length streaming mode set");248}249chunkLength = chunklen <=0? DEFAULT_CHUNK_SIZE : chunklen;250}251252/**253* Returns the value for the {@code n}<sup>th</sup> header field.254* Some implementations may treat the {@code 0}<sup>th</sup>255* header field as special, i.e. as the status line returned by the HTTP256* server.257* <p>258* This method can be used in conjunction with the259* {@link #getHeaderFieldKey getHeaderFieldKey} method to iterate through all260* the headers in the message.261*262* @param n an index, where {@code n>=0}.263* @return the value of the {@code n}<sup>th</sup> header field,264* or {@code null} if the value does not exist.265* @see java.net.HttpURLConnection#getHeaderFieldKey(int)266*/267public String getHeaderField(int n) {268return null;269}270271/**272* An {@code int} representing the three digit HTTP Status-Code.273* <ul>274* <li> 1xx: Informational275* <li> 2xx: Success276* <li> 3xx: Redirection277* <li> 4xx: Client Error278* <li> 5xx: Server Error279* </ul>280*/281protected int responseCode = -1;282283/**284* The HTTP response message.285*/286protected String responseMessage = null;287288/* static variables */289290/* do we automatically follow redirects? The default is true. */291private static boolean followRedirects = true;292293/**294* If {@code true}, the protocol will automatically follow redirects.295* If {@code false}, the protocol will not automatically follow296* redirects.297* <p>298* This field is set by the {@code setInstanceFollowRedirects}299* method. Its value is returned by the {@code getInstanceFollowRedirects}300* method.301* <p>302* Its default value is based on the value of the static followRedirects303* at HttpURLConnection construction time.304*305* @see java.net.HttpURLConnection#setInstanceFollowRedirects(boolean)306* @see java.net.HttpURLConnection#getInstanceFollowRedirects()307* @see java.net.HttpURLConnection#setFollowRedirects(boolean)308*/309protected boolean instanceFollowRedirects = followRedirects;310311/* valid HTTP methods */312private static final String[] methods = {313"GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE"314};315316/**317* Constructor for the HttpURLConnection.318* @param u the URL319*/320protected HttpURLConnection (URL u) {321super(u);322}323324/**325* Sets whether HTTP redirects (requests with response code 3xx) should326* be automatically followed by this class. True by default. Applets327* cannot change this variable.328* <p>329* If there is a security manager, this method first calls330* the security manager's {@code checkSetFactory} method331* to ensure the operation is allowed.332* This could result in a SecurityException.333*334* @param set a {@code boolean} indicating whether or not335* to follow HTTP redirects.336* @exception SecurityException if a security manager exists and its337* {@code checkSetFactory} method doesn't338* allow the operation.339* @see SecurityManager#checkSetFactory340* @see #getFollowRedirects()341*/342public static void setFollowRedirects(boolean set) {343SecurityManager sec = System.getSecurityManager();344if (sec != null) {345// seems to be the best check here...346sec.checkSetFactory();347}348followRedirects = set;349}350351/**352* Returns a {@code boolean} indicating353* whether or not HTTP redirects (3xx) should354* be automatically followed.355*356* @return {@code true} if HTTP redirects should357* be automatically followed, {@code false} if not.358* @see #setFollowRedirects(boolean)359*/360public static boolean getFollowRedirects() {361return followRedirects;362}363364/**365* Sets whether HTTP redirects (requests with response code 3xx) should366* be automatically followed by this {@code HttpURLConnection}367* instance.368* <p>369* The default value comes from followRedirects, which defaults to370* true.371*372* @param followRedirects a {@code boolean} indicating373* whether or not to follow HTTP redirects.374*375* @see java.net.HttpURLConnection#instanceFollowRedirects376* @see #getInstanceFollowRedirects377* @since 1.3378*/379public void setInstanceFollowRedirects(boolean followRedirects) {380instanceFollowRedirects = followRedirects;381}382383/**384* Returns the value of this {@code HttpURLConnection}'s385* {@code instanceFollowRedirects} field.386*387* @return the value of this {@code HttpURLConnection}'s388* {@code instanceFollowRedirects} field.389* @see java.net.HttpURLConnection#instanceFollowRedirects390* @see #setInstanceFollowRedirects(boolean)391* @since 1.3392*/393public boolean getInstanceFollowRedirects() {394return instanceFollowRedirects;395}396397/**398* Set the method for the URL request, one of:399* <UL>400* <LI>GET401* <LI>POST402* <LI>HEAD403* <LI>OPTIONS404* <LI>PUT405* <LI>DELETE406* <LI>TRACE407* </UL> are legal, subject to protocol restrictions. The default408* method is GET.409*410* @param method the HTTP method411* @exception ProtocolException if the method cannot be reset or if412* the requested method isn't valid for HTTP.413* @exception SecurityException if a security manager is set and the414* method is "TRACE", but the "allowHttpTrace"415* NetPermission is not granted.416* @see #getRequestMethod()417*/418public void setRequestMethod(String method) throws ProtocolException {419if (connected) {420throw new ProtocolException("Can't reset method: already connected");421}422// This restriction will prevent people from using this class to423// experiment w/ new HTTP methods using java. But it should424// be placed for security - the request String could be425// arbitrarily long.426427for (int i = 0; i < methods.length; i++) {428if (methods[i].equals(method)) {429if (method.equals("TRACE")) {430SecurityManager s = System.getSecurityManager();431if (s != null) {432s.checkPermission(new NetPermission("allowHttpTrace"));433}434}435this.method = method;436return;437}438}439throw new ProtocolException("Invalid HTTP method: " + method);440}441442/**443* Get the request method.444* @return the HTTP request method445* @see #setRequestMethod(java.lang.String)446*/447public String getRequestMethod() {448return method;449}450451/**452* Gets the status code from an HTTP response message.453* For example, in the case of the following status lines:454* <PRE>455* HTTP/1.0 200 OK456* HTTP/1.0 401 Unauthorized457* </PRE>458* It will return 200 and 401 respectively.459* Returns -1 if no code can be discerned460* from the response (i.e., the response is not valid HTTP).461* @throws IOException if an error occurred connecting to the server.462* @return the HTTP Status-Code, or -1463*/464public int getResponseCode() throws IOException {465/*466* We're got the response code already467*/468if (responseCode != -1) {469return responseCode;470}471472/*473* Ensure that we have connected to the server. Record474* exception as we need to re-throw it if there isn't475* a status line.476*/477Exception exc = null;478try {479getInputStream();480} catch (Exception e) {481exc = e;482}483484/*485* If we can't a status-line then re-throw any exception486* that getInputStream threw.487*/488String statusLine = getHeaderField(0);489if (statusLine == null) {490if (exc != null) {491if (exc instanceof RuntimeException)492throw (RuntimeException)exc;493else494throw (IOException)exc;495}496return -1;497}498499/*500* Examine the status-line - should be formatted as per501* section 6.1 of RFC 2616 :-502*503* Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase504*505* If status line can't be parsed return -1.506*/507if (statusLine.startsWith("HTTP/1.")) {508int codePos = statusLine.indexOf(' ');509if (codePos > 0) {510511int phrasePos = statusLine.indexOf(' ', codePos+1);512if (phrasePos > 0 && phrasePos < statusLine.length()) {513responseMessage = statusLine.substring(phrasePos+1);514}515516// deviation from RFC 2616 - don't reject status line517// if SP Reason-Phrase is not included.518if (phrasePos < 0)519phrasePos = statusLine.length();520521try {522responseCode = Integer.parseInt523(statusLine.substring(codePos+1, phrasePos));524return responseCode;525} catch (NumberFormatException e) { }526}527}528return -1;529}530531/**532* Gets the HTTP response message, if any, returned along with the533* response code from a server. From responses like:534* <PRE>535* HTTP/1.0 200 OK536* HTTP/1.0 404 Not Found537* </PRE>538* Extracts the Strings "OK" and "Not Found" respectively.539* Returns null if none could be discerned from the responses540* (the result was not valid HTTP).541* @throws IOException if an error occurred connecting to the server.542* @return the HTTP response message, or {@code null}543*/544public String getResponseMessage() throws IOException {545getResponseCode();546return responseMessage;547}548549@SuppressWarnings("deprecation")550public long getHeaderFieldDate(String name, long Default) {551String dateString = getHeaderField(name);552try {553if (dateString.indexOf("GMT") == -1) {554dateString = dateString+" GMT";555}556return Date.parse(dateString);557} catch (Exception e) {558}559return Default;560}561562563/**564* Indicates that other requests to the server565* are unlikely in the near future. Calling disconnect()566* should not imply that this HttpURLConnection567* instance can be reused for other requests.568*/569public abstract void disconnect();570571/**572* Indicates if the connection is going through a proxy.573* @return a boolean indicating if the connection is574* using a proxy.575*/576public abstract boolean usingProxy();577578/**579* Returns a {@link SocketPermission} object representing the580* permission necessary to connect to the destination host and port.581*582* @exception IOException if an error occurs while computing583* the permission.584*585* @return a {@code SocketPermission} object representing the586* permission necessary to connect to the destination587* host and port.588*/589public Permission getPermission() throws IOException {590int port = url.getPort();591port = port < 0 ? 80 : port;592String host = url.getHost() + ":" + port;593Permission permission = new SocketPermission(host, "connect");594return permission;595}596597/**598* Returns the error stream if the connection failed599* but the server sent useful data nonetheless. The600* typical example is when an HTTP server responds601* with a 404, which will cause a FileNotFoundException602* to be thrown in connect, but the server sent an HTML603* help page with suggestions as to what to do.604*605* <p>This method will not cause a connection to be initiated. If606* the connection was not connected, or if the server did not have607* an error while connecting or if the server had an error but608* no error data was sent, this method will return null. This is609* the default.610*611* @return an error stream if any, null if there have been no612* errors, the connection is not connected or the server sent no613* useful data.614*/615public InputStream getErrorStream() {616return null;617}618619/**620* The response codes for HTTP, as of version 1.1.621*/622623// REMIND: do we want all these??624// Others not here that we do want??625626/* 2XX: generally "OK" */627628/**629* HTTP Status-Code 200: OK.630*/631public static final int HTTP_OK = 200;632633/**634* HTTP Status-Code 201: Created.635*/636public static final int HTTP_CREATED = 201;637638/**639* HTTP Status-Code 202: Accepted.640*/641public static final int HTTP_ACCEPTED = 202;642643/**644* HTTP Status-Code 203: Non-Authoritative Information.645*/646public static final int HTTP_NOT_AUTHORITATIVE = 203;647648/**649* HTTP Status-Code 204: No Content.650*/651public static final int HTTP_NO_CONTENT = 204;652653/**654* HTTP Status-Code 205: Reset Content.655*/656public static final int HTTP_RESET = 205;657658/**659* HTTP Status-Code 206: Partial Content.660*/661public static final int HTTP_PARTIAL = 206;662663/* 3XX: relocation/redirect */664665/**666* HTTP Status-Code 300: Multiple Choices.667*/668public static final int HTTP_MULT_CHOICE = 300;669670/**671* HTTP Status-Code 301: Moved Permanently.672*/673public static final int HTTP_MOVED_PERM = 301;674675/**676* HTTP Status-Code 302: Temporary Redirect.677*/678public static final int HTTP_MOVED_TEMP = 302;679680/**681* HTTP Status-Code 303: See Other.682*/683public static final int HTTP_SEE_OTHER = 303;684685/**686* HTTP Status-Code 304: Not Modified.687*/688public static final int HTTP_NOT_MODIFIED = 304;689690/**691* HTTP Status-Code 305: Use Proxy.692*/693public static final int HTTP_USE_PROXY = 305;694695/* 4XX: client error */696697/**698* HTTP Status-Code 400: Bad Request.699*/700public static final int HTTP_BAD_REQUEST = 400;701702/**703* HTTP Status-Code 401: Unauthorized.704*/705public static final int HTTP_UNAUTHORIZED = 401;706707/**708* HTTP Status-Code 402: Payment Required.709*/710public static final int HTTP_PAYMENT_REQUIRED = 402;711712/**713* HTTP Status-Code 403: Forbidden.714*/715public static final int HTTP_FORBIDDEN = 403;716717/**718* HTTP Status-Code 404: Not Found.719*/720public static final int HTTP_NOT_FOUND = 404;721722/**723* HTTP Status-Code 405: Method Not Allowed.724*/725public static final int HTTP_BAD_METHOD = 405;726727/**728* HTTP Status-Code 406: Not Acceptable.729*/730public static final int HTTP_NOT_ACCEPTABLE = 406;731732/**733* HTTP Status-Code 407: Proxy Authentication Required.734*/735public static final int HTTP_PROXY_AUTH = 407;736737/**738* HTTP Status-Code 408: Request Time-Out.739*/740public static final int HTTP_CLIENT_TIMEOUT = 408;741742/**743* HTTP Status-Code 409: Conflict.744*/745public static final int HTTP_CONFLICT = 409;746747/**748* HTTP Status-Code 410: Gone.749*/750public static final int HTTP_GONE = 410;751752/**753* HTTP Status-Code 411: Length Required.754*/755public static final int HTTP_LENGTH_REQUIRED = 411;756757/**758* HTTP Status-Code 412: Precondition Failed.759*/760public static final int HTTP_PRECON_FAILED = 412;761762/**763* HTTP Status-Code 413: Request Entity Too Large.764*/765public static final int HTTP_ENTITY_TOO_LARGE = 413;766767/**768* HTTP Status-Code 414: Request-URI Too Large.769*/770public static final int HTTP_REQ_TOO_LONG = 414;771772/**773* HTTP Status-Code 415: Unsupported Media Type.774*/775public static final int HTTP_UNSUPPORTED_TYPE = 415;776777/* 5XX: server error */778779/**780* HTTP Status-Code 500: Internal Server Error.781* @deprecated it is misplaced and shouldn't have existed.782*/783@Deprecated784public static final int HTTP_SERVER_ERROR = 500;785786/**787* HTTP Status-Code 500: Internal Server Error.788*/789public static final int HTTP_INTERNAL_ERROR = 500;790791/**792* HTTP Status-Code 501: Not Implemented.793*/794public static final int HTTP_NOT_IMPLEMENTED = 501;795796/**797* HTTP Status-Code 502: Bad Gateway.798*/799public static final int HTTP_BAD_GATEWAY = 502;800801/**802* HTTP Status-Code 503: Service Unavailable.803*/804public static final int HTTP_UNAVAILABLE = 503;805806/**807* HTTP Status-Code 504: Gateway Timeout.808*/809public static final int HTTP_GATEWAY_TIMEOUT = 504;810811/**812* HTTP Status-Code 505: HTTP Version Not Supported.813*/814public static final int HTTP_VERSION = 505;815816}817818819