Path: blob/master/src/java.base/share/classes/java/net/HttpURLConnection.java
41152 views
/*1* Copyright (c) 1996, 2021, 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 1.167*/68public abstract 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* Supplies an {@link java.net.Authenticator Authenticator} to be used106* when authentication is requested through the HTTP protocol for107* this {@code HttpURLConnection}.108* If no authenticator is supplied, the109* {@linkplain Authenticator#setDefault(java.net.Authenticator) default110* authenticator} will be used.111*112* @implSpec The default behavior of this method is to unconditionally113* throw {@link UnsupportedOperationException}. Concrete114* implementations of {@code HttpURLConnection}115* which support supplying an {@code Authenticator} for a116* specific {@code HttpURLConnection} instance should117* override this method to implement a different behavior.118*119* @implNote Depending on authentication schemes, an implementation120* may or may not need to use the provided authenticator121* to obtain a password. For instance, an implementation that122* relies on third-party security libraries may still invoke the123* default authenticator if these libraries are configured124* to do so.125* Likewise, an implementation that supports transparent126* NTLM authentication may let the system attempt127* to connect using the system user credentials first,128* before invoking the provided authenticator.129* <br>130* However, if an authenticator is specifically provided,131* then the underlying connection may only be reused for132* {@code HttpURLConnection} instances which share the same133* {@code Authenticator} instance, and authentication information,134* if cached, may only be reused for an {@code HttpURLConnection}135* sharing that same {@code Authenticator}.136*137* @param auth The {@code Authenticator} that should be used by this138* {@code HttpURLConnection}.139*140* @throws UnsupportedOperationException if setting an Authenticator is141* not supported by the underlying implementation.142* @throws IllegalStateException if URLConnection is already connected.143* @throws NullPointerException if the supplied {@code auth} is {@code null}.144* @since 9145*/146public void setAuthenticator(Authenticator auth) {147throw new UnsupportedOperationException("Supplying an authenticator"148+ " is not supported by " + this.getClass());149}150151/**152* Returns the key for the {@code n}<sup>th</sup> header field.153* Some implementations may treat the {@code 0}<sup>th</sup>154* header field as special, i.e. as the status line returned by the HTTP155* server. In this case, {@link #getHeaderField(int) getHeaderField(0)} returns the status156* line, but {@code getHeaderFieldKey(0)} returns null.157*158* @param n an index, where {@code n >=0}.159* @return the key for the {@code n}<sup>th</sup> header field,160* or {@code null} if the key does not exist.161*/162public String getHeaderFieldKey (int n) {163return null;164}165166/**167* This method is used to enable streaming of a HTTP request body168* without internal buffering, when the content length is known in169* advance.170* <p>171* An exception will be thrown if the application172* attempts to write more data than the indicated173* content-length, or if the application closes the OutputStream174* before writing the indicated amount.175* <p>176* When output streaming is enabled, authentication177* and redirection cannot be handled automatically.178* A HttpRetryException will be thrown when reading179* the response if authentication or redirection are required.180* This exception can be queried for the details of the error.181* <p>182* This method must be called before the URLConnection is connected.183* <p>184* <B>NOTE:</B> {@link #setFixedLengthStreamingMode(long)} is recommended185* instead of this method as it allows larger content lengths to be set.186*187* @param contentLength The number of bytes which will be written188* to the OutputStream.189*190* @throws IllegalStateException if URLConnection is already connected191* or if a different streaming mode is already enabled.192*193* @throws IllegalArgumentException if a content length less than194* zero is specified.195*196* @see #setChunkedStreamingMode(int)197* @since 1.5198*/199public void setFixedLengthStreamingMode (int contentLength) {200if (connected) {201throw new IllegalStateException ("Already connected");202}203if (chunkLength != -1) {204throw new IllegalStateException ("Chunked encoding streaming mode set");205}206if (contentLength < 0) {207throw new IllegalArgumentException ("invalid content length");208}209fixedContentLength = contentLength;210}211212/**213* This method is used to enable streaming of a HTTP request body214* without internal buffering, when the content length is known in215* advance.216*217* <P> An exception will be thrown if the application attempts to write218* more data than the indicated content-length, or if the application219* closes the OutputStream before writing the indicated amount.220*221* <P> When output streaming is enabled, authentication and redirection222* cannot be handled automatically. A {@linkplain HttpRetryException} will223* be thrown when reading the response if authentication or redirection224* are required. This exception can be queried for the details of the225* error.226*227* <P> This method must be called before the URLConnection is connected.228*229* <P> The content length set by invoking this method takes precedence230* over any value set by {@link #setFixedLengthStreamingMode(int)}.231*232* @param contentLength233* The number of bytes which will be written to the OutputStream.234*235* @throws IllegalStateException236* if URLConnection is already connected or if a different237* streaming mode is already enabled.238*239* @throws IllegalArgumentException240* if a content length less than zero is specified.241*242* @since 1.7243*/244public void setFixedLengthStreamingMode(long contentLength) {245if (connected) {246throw new IllegalStateException("Already connected");247}248if (chunkLength != -1) {249throw new IllegalStateException(250"Chunked encoding streaming mode set");251}252if (contentLength < 0) {253throw new IllegalArgumentException("invalid content length");254}255fixedContentLengthLong = contentLength;256}257258/* Default chunk size (including chunk header) if not specified;259* we want to keep this in sync with the one defined in260* sun.net.www.http.ChunkedOutputStream261*/262private static final int DEFAULT_CHUNK_SIZE = 4096;263264/**265* This method is used to enable streaming of a HTTP request body266* without internal buffering, when the content length is <b>not</b>267* known in advance. In this mode, chunked transfer encoding268* is used to send the request body. Note, not all HTTP servers269* support this mode.270* <p>271* When output streaming is enabled, authentication272* and redirection cannot be handled automatically.273* A HttpRetryException will be thrown when reading274* the response if authentication or redirection are required.275* This exception can be queried for the details of the error.276* <p>277* This method must be called before the URLConnection is connected.278*279* @param chunklen The number of bytes to write in each chunk.280* If chunklen is less than or equal to zero, a default281* value will be used.282*283* @throws IllegalStateException if URLConnection is already connected284* or if a different streaming mode is already enabled.285*286* @see #setFixedLengthStreamingMode(int)287* @since 1.5288*/289public void setChunkedStreamingMode (int chunklen) {290if (connected) {291throw new IllegalStateException ("Can't set streaming mode: already connected");292}293if (fixedContentLength != -1 || fixedContentLengthLong != -1) {294throw new IllegalStateException ("Fixed length streaming mode set");295}296chunkLength = chunklen <=0? DEFAULT_CHUNK_SIZE : chunklen;297}298299/**300* Returns the value for the {@code n}<sup>th</sup> header field.301* Some implementations may treat the {@code 0}<sup>th</sup>302* header field as special, i.e. as the status line returned by the HTTP303* server.304* <p>305* This method can be used in conjunction with the306* {@link #getHeaderFieldKey getHeaderFieldKey} method to iterate through all307* the headers in the message.308*309* @param n an index, where {@code n>=0}.310* @return the value of the {@code n}<sup>th</sup> header field,311* or {@code null} if the value does not exist.312* @see java.net.HttpURLConnection#getHeaderFieldKey(int)313*/314public String getHeaderField(int n) {315return null;316}317318/**319* An {@code int} representing the three digit HTTP Status-Code.320* <ul>321* <li> 1xx: Informational322* <li> 2xx: Success323* <li> 3xx: Redirection324* <li> 4xx: Client Error325* <li> 5xx: Server Error326* </ul>327*/328protected int responseCode = -1;329330/**331* The HTTP response message.332*/333protected String responseMessage = null;334335/* static variables */336337/* do we automatically follow redirects? The default is true. */338private static boolean followRedirects = true;339340/**341* If {@code true}, the protocol will automatically follow redirects.342* If {@code false}, the protocol will not automatically follow343* redirects.344* <p>345* This field is set by the {@code setInstanceFollowRedirects}346* method. Its value is returned by the {@code getInstanceFollowRedirects}347* method.348* <p>349* Its default value is based on the value of the static followRedirects350* at HttpURLConnection construction time.351*352* @see java.net.HttpURLConnection#setInstanceFollowRedirects(boolean)353* @see java.net.HttpURLConnection#getInstanceFollowRedirects()354* @see java.net.HttpURLConnection#setFollowRedirects(boolean)355*/356protected boolean instanceFollowRedirects = followRedirects;357358/* valid HTTP methods */359private static final String[] methods = {360"GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE"361};362363/**364* Constructor for the HttpURLConnection.365* @param u the URL366*/367protected HttpURLConnection (URL u) {368super(u);369}370371/**372* Sets whether HTTP redirects (requests with response code 3xx) should373* be automatically followed by this class. True by default. Applets374* cannot change this variable.375* <p>376* If there is a security manager, this method first calls377* the security manager's {@code checkSetFactory} method378* to ensure the operation is allowed.379* This could result in a SecurityException.380*381* @param set a {@code boolean} indicating whether or not382* to follow HTTP redirects.383* @throws SecurityException if a security manager exists and its384* {@code checkSetFactory} method doesn't385* allow the operation.386* @see SecurityManager#checkSetFactory387* @see #getFollowRedirects()388*/389public static void setFollowRedirects(boolean set) {390@SuppressWarnings("removal")391SecurityManager sec = System.getSecurityManager();392if (sec != null) {393// seems to be the best check here...394sec.checkSetFactory();395}396followRedirects = set;397}398399/**400* Returns a {@code boolean} indicating401* whether or not HTTP redirects (3xx) should402* be automatically followed.403*404* @return {@code true} if HTTP redirects should405* be automatically followed, {@code false} if not.406* @see #setFollowRedirects(boolean)407*/408public static boolean getFollowRedirects() {409return followRedirects;410}411412/**413* Sets whether HTTP redirects (requests with response code 3xx) should414* be automatically followed by this {@code HttpURLConnection}415* instance.416* <p>417* The default value comes from followRedirects, which defaults to418* true.419*420* @param followRedirects a {@code boolean} indicating421* whether or not to follow HTTP redirects.422*423* @see java.net.HttpURLConnection#instanceFollowRedirects424* @see #getInstanceFollowRedirects425* @since 1.3426*/427public void setInstanceFollowRedirects(boolean followRedirects) {428instanceFollowRedirects = followRedirects;429}430431/**432* Returns the value of this {@code HttpURLConnection}'s433* {@code instanceFollowRedirects} field.434*435* @return the value of this {@code HttpURLConnection}'s436* {@code instanceFollowRedirects} field.437* @see java.net.HttpURLConnection#instanceFollowRedirects438* @see #setInstanceFollowRedirects(boolean)439* @since 1.3440*/441public boolean getInstanceFollowRedirects() {442return instanceFollowRedirects;443}444445/**446* Set the method for the URL request, one of:447* <UL>448* <LI>GET449* <LI>POST450* <LI>HEAD451* <LI>OPTIONS452* <LI>PUT453* <LI>DELETE454* <LI>TRACE455* </UL> are legal, subject to protocol restrictions. The default456* method is GET.457*458* @param method the HTTP method459* @throws ProtocolException if the method cannot be reset or if460* the requested method isn't valid for HTTP.461* @throws SecurityException if a security manager is set and the462* method is "TRACE", but the "allowHttpTrace"463* NetPermission is not granted.464* @see #getRequestMethod()465*/466public void setRequestMethod(String method) throws ProtocolException {467if (connected) {468throw new ProtocolException("Can't reset method: already connected");469}470// This restriction will prevent people from using this class to471// experiment w/ new HTTP methods using java. But it should472// be placed for security - the request String could be473// arbitrarily long.474475for (int i = 0; i < methods.length; i++) {476if (methods[i].equals(method)) {477if (method.equals("TRACE")) {478@SuppressWarnings("removal")479SecurityManager s = System.getSecurityManager();480if (s != null) {481s.checkPermission(new NetPermission("allowHttpTrace"));482}483}484this.method = method;485return;486}487}488throw new ProtocolException("Invalid HTTP method: " + method);489}490491/**492* Get the request method.493* @return the HTTP request method494* @see #setRequestMethod(java.lang.String)495*/496public String getRequestMethod() {497return method;498}499500/**501* Gets the status code from an HTTP response message.502* For example, in the case of the following status lines:503* <PRE>504* HTTP/1.0 200 OK505* HTTP/1.0 401 Unauthorized506* </PRE>507* It will return 200 and 401 respectively.508* Returns -1 if no code can be discerned509* from the response (i.e., the response is not valid HTTP).510* @throws IOException if an error occurred connecting to the server.511* @return the HTTP Status-Code, or -1512*/513public int getResponseCode() throws IOException {514/*515* We've got the response code already516*/517if (responseCode != -1) {518return responseCode;519}520521/*522* Ensure that we have connected to the server. Record523* exception as we need to re-throw it if there isn't524* a status line.525*/526Exception exc = null;527try {528getInputStream();529} catch (Exception e) {530exc = e;531}532533/*534* If we can't find a status-line then re-throw any exception535* that getInputStream threw.536*/537String statusLine = getHeaderField(0);538if (statusLine == null) {539if (exc != null) {540if (exc instanceof RuntimeException)541throw (RuntimeException)exc;542else543throw (IOException)exc;544}545return -1;546}547548/*549* Examine the status-line - should be formatted as per550* section 6.1 of RFC 2616 :-551*552* Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase553*554* If status line can't be parsed return -1.555*/556if (statusLine.startsWith("HTTP/1.")) {557int codePos = statusLine.indexOf(' ');558if (codePos > 0) {559560int phrasePos = statusLine.indexOf(' ', codePos+1);561if (phrasePos > 0 && phrasePos < statusLine.length()) {562responseMessage = statusLine.substring(phrasePos+1);563}564565// deviation from RFC 2616 - don't reject status line566// if SP Reason-Phrase is not included.567if (phrasePos < 0)568phrasePos = statusLine.length();569570try {571responseCode = Integer.parseInt572(statusLine.substring(codePos+1, phrasePos));573return responseCode;574} catch (NumberFormatException e) { }575}576}577return -1;578}579580/**581* Gets the HTTP response message, if any, returned along with the582* response code from a server. From responses like:583* <PRE>584* HTTP/1.0 200 OK585* HTTP/1.0 404 Not Found586* </PRE>587* Extracts the Strings "OK" and "Not Found" respectively.588* Returns null if none could be discerned from the responses589* (the result was not valid HTTP).590* @throws IOException if an error occurred connecting to the server.591* @return the HTTP response message, or {@code null}592*/593public String getResponseMessage() throws IOException {594getResponseCode();595return responseMessage;596}597598@SuppressWarnings("deprecation")599public long getHeaderFieldDate(String name, long Default) {600String dateString = getHeaderField(name);601try {602if (dateString.indexOf("GMT") == -1) {603dateString = dateString+" GMT";604}605return Date.parse(dateString);606} catch (Exception e) {607}608return Default;609}610611612/**613* Indicates that other requests to the server614* are unlikely in the near future. Calling disconnect()615* should not imply that this HttpURLConnection616* instance can be reused for other requests.617*/618public abstract void disconnect();619620/**621* Indicates if the connection is going through a proxy.622*623* This method returns {@code true} if the connection is known624* to be going or has gone through proxies, and returns {@code false}625* if the connection will never go through a proxy or if626* the use of a proxy cannot be determined.627*628* @return a boolean indicating if the connection is using a proxy.629*/630public abstract boolean usingProxy();631632/**633* Returns a {@link SocketPermission} object representing the634* permission necessary to connect to the destination host and port.635*636* @throws IOException if an error occurs while computing637* the permission.638*639* @return a {@code SocketPermission} object representing the640* permission necessary to connect to the destination641* host and port.642*/643public Permission getPermission() throws IOException {644int port = url.getPort();645port = port < 0 ? 80 : port;646String host = url.getHost() + ":" + port;647Permission permission = new SocketPermission(host, "connect");648return permission;649}650651/**652* Returns the error stream if the connection failed653* but the server sent useful data nonetheless. The654* typical example is when an HTTP server responds655* with a 404, which will cause a FileNotFoundException656* to be thrown in connect, but the server sent an HTML657* help page with suggestions as to what to do.658*659* <p>This method will not cause a connection to be initiated. If660* the connection was not connected, or if the server did not have661* an error while connecting or if the server had an error but662* no error data was sent, this method will return null. This is663* the default.664*665* @return an error stream if any, null if there have been no666* errors, the connection is not connected or the server sent no667* useful data.668*/669public InputStream getErrorStream() {670return null;671}672673/**674* The response codes for HTTP, as of version 1.1.675*/676677// REMIND: do we want all these??678// Others not here that we do want??679680/* 2XX: generally "OK" */681682/**683* HTTP Status-Code 200: OK.684*/685public static final int HTTP_OK = 200;686687/**688* HTTP Status-Code 201: Created.689*/690public static final int HTTP_CREATED = 201;691692/**693* HTTP Status-Code 202: Accepted.694*/695public static final int HTTP_ACCEPTED = 202;696697/**698* HTTP Status-Code 203: Non-Authoritative Information.699*/700public static final int HTTP_NOT_AUTHORITATIVE = 203;701702/**703* HTTP Status-Code 204: No Content.704*/705public static final int HTTP_NO_CONTENT = 204;706707/**708* HTTP Status-Code 205: Reset Content.709*/710public static final int HTTP_RESET = 205;711712/**713* HTTP Status-Code 206: Partial Content.714*/715public static final int HTTP_PARTIAL = 206;716717/* 3XX: relocation/redirect */718719/**720* HTTP Status-Code 300: Multiple Choices.721*/722public static final int HTTP_MULT_CHOICE = 300;723724/**725* HTTP Status-Code 301: Moved Permanently.726*/727public static final int HTTP_MOVED_PERM = 301;728729/**730* HTTP Status-Code 302: Temporary Redirect.731*/732public static final int HTTP_MOVED_TEMP = 302;733734/**735* HTTP Status-Code 303: See Other.736*/737public static final int HTTP_SEE_OTHER = 303;738739/**740* HTTP Status-Code 304: Not Modified.741*/742public static final int HTTP_NOT_MODIFIED = 304;743744/**745* HTTP Status-Code 305: Use Proxy.746*/747public static final int HTTP_USE_PROXY = 305;748749/* 4XX: client error */750751/**752* HTTP Status-Code 400: Bad Request.753*/754public static final int HTTP_BAD_REQUEST = 400;755756/**757* HTTP Status-Code 401: Unauthorized.758*/759public static final int HTTP_UNAUTHORIZED = 401;760761/**762* HTTP Status-Code 402: Payment Required.763*/764public static final int HTTP_PAYMENT_REQUIRED = 402;765766/**767* HTTP Status-Code 403: Forbidden.768*/769public static final int HTTP_FORBIDDEN = 403;770771/**772* HTTP Status-Code 404: Not Found.773*/774public static final int HTTP_NOT_FOUND = 404;775776/**777* HTTP Status-Code 405: Method Not Allowed.778*/779public static final int HTTP_BAD_METHOD = 405;780781/**782* HTTP Status-Code 406: Not Acceptable.783*/784public static final int HTTP_NOT_ACCEPTABLE = 406;785786/**787* HTTP Status-Code 407: Proxy Authentication Required.788*/789public static final int HTTP_PROXY_AUTH = 407;790791/**792* HTTP Status-Code 408: Request Time-Out.793*/794public static final int HTTP_CLIENT_TIMEOUT = 408;795796/**797* HTTP Status-Code 409: Conflict.798*/799public static final int HTTP_CONFLICT = 409;800801/**802* HTTP Status-Code 410: Gone.803*/804public static final int HTTP_GONE = 410;805806/**807* HTTP Status-Code 411: Length Required.808*/809public static final int HTTP_LENGTH_REQUIRED = 411;810811/**812* HTTP Status-Code 412: Precondition Failed.813*/814public static final int HTTP_PRECON_FAILED = 412;815816/**817* HTTP Status-Code 413: Request Entity Too Large.818*/819public static final int HTTP_ENTITY_TOO_LARGE = 413;820821/**822* HTTP Status-Code 414: Request-URI Too Large.823*/824public static final int HTTP_REQ_TOO_LONG = 414;825826/**827* HTTP Status-Code 415: Unsupported Media Type.828*/829public static final int HTTP_UNSUPPORTED_TYPE = 415;830831/* 5XX: server error */832833/**834* HTTP Status-Code 500: Internal Server Error.835* @deprecated it is misplaced and shouldn't have existed.836*/837@Deprecated838public static final int HTTP_SERVER_ERROR = 500;839840/**841* HTTP Status-Code 500: Internal Server Error.842*/843public static final int HTTP_INTERNAL_ERROR = 500;844845/**846* HTTP Status-Code 501: Not Implemented.847*/848public static final int HTTP_NOT_IMPLEMENTED = 501;849850/**851* HTTP Status-Code 502: Bad Gateway.852*/853public static final int HTTP_BAD_GATEWAY = 502;854855/**856* HTTP Status-Code 503: Service Unavailable.857*/858public static final int HTTP_UNAVAILABLE = 503;859860/**861* HTTP Status-Code 504: Gateway Timeout.862*/863public static final int HTTP_GATEWAY_TIMEOUT = 504;864865/**866* HTTP Status-Code 505: HTTP Version Not Supported.867*/868public static final int HTTP_VERSION = 505;869870}871872873