1. /*
  2. * @(#)HttpURLConnection.java 1.25 00/02/02
  3. *
  4. * Copyright 1996-2000 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. package java.net;
  11. import java.io.InputStream;
  12. import java.io.IOException;
  13. import java.security.Permission;
  14. import java.util.Date;
  15. /**
  16. * A URLConnection with support for HTTP-specific features. See
  17. * <A HREF="http://www.w3.org/pub/WWW/Protocols/"> the spec </A> for
  18. * details.
  19. * <p>
  20. *
  21. * Each HttpURLConnection instance is used to make a single request
  22. * but the underlying network connection to the HTTP server may be
  23. * transparently shared by other instances. Calling the close() methods
  24. * on the InputStream or OutputStream of an HttpURLConnection
  25. * after a request may free network resources associated with this
  26. * instance but has no effect on any shared persistent connection.
  27. * Calling the disconnect() method may close the underlying socket
  28. * if a persistent connection is otherwise idle at that time.
  29. *
  30. * @see java.net.HttpURLConnection#disconnect()
  31. * @since JDK1.1
  32. */
  33. abstract public class HttpURLConnection extends URLConnection {
  34. /* instance variables */
  35. /**
  36. * The HTTP method (GET,POST,PUT,etc.).
  37. */
  38. protected String method = "GET";
  39. /**
  40. * An <code>int</code> representing the three digit HTTP Status-Code.
  41. * <ul>
  42. * <li> 1xx: Informational
  43. * <li> 2xx: Success
  44. * <li> 3xx: Redirection
  45. * <li> 4xx: Client Error
  46. * <li> 5xx: Server Error
  47. * </ul>
  48. */
  49. protected int responseCode = -1;
  50. /**
  51. * The HTTP response message.
  52. */
  53. protected String responseMessage = null;
  54. /* static variables */
  55. /* do we automatically follow redirects? The default is true. */
  56. private static boolean followRedirects = true;
  57. /**
  58. * If <code>true</code>, the protocol will automatically follow redirects.
  59. * If <code>false</code>, the protocol will not automatically follow
  60. * redirects.
  61. * <p>
  62. * This field is set by the <code>setInstanceFollowRedirects</code>
  63. * method. Its value is returned by the <code>getInstanceFollowRedirects</code>
  64. * method.
  65. * <p>
  66. * Its default value is based on the value of the static followRedirects
  67. * at HttpURLConnection construction time.
  68. *
  69. * @see java.net.HttpURLConnection#setInstanceFollowRedirects(boolean)
  70. * @see java.net.HttpURLConnection#getInstanceFollowRedirects()
  71. * @see java.net.HttpURLConnection#setFollowRedirects(boolean)
  72. */
  73. protected boolean instanceFollowRedirects = followRedirects;
  74. /* valid HTTP methods */
  75. private static final String[] methods = {
  76. "GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE"
  77. };
  78. /**
  79. * Constructor for the URLStreamHandler.
  80. * @param u the URL
  81. */
  82. protected HttpURLConnection (URL u) {
  83. super(u);
  84. }
  85. /**
  86. * Sets whether HTTP redirects (requests with response code 3xx) should
  87. * be automatically followed by this class. True by default. Applets
  88. * cannot change this variable.
  89. * <p>
  90. * If there is a security manager, this method first calls
  91. * the security manager's <code>checkSetFactory</code> method
  92. * to ensure the operation is allowed.
  93. * This could result in a SecurityException.
  94. *
  95. * @param set a <code>boolean</code> indicating whether or not
  96. * to follow HTTP redirects.
  97. * @exception SecurityException if a security manager exists and its
  98. * <code>checkSetFactory</code> method doesn't
  99. * allow the operation.
  100. * @see SecurityManager#checkSetFactory
  101. * @see #getFollowRedirects()
  102. */
  103. public static void setFollowRedirects(boolean set) {
  104. SecurityManager sec = System.getSecurityManager();
  105. if (sec != null) {
  106. // seems to be the best check here...
  107. sec.checkSetFactory();
  108. }
  109. followRedirects = set;
  110. }
  111. /**
  112. * Returns a <code>boolean</code> indicating
  113. * whether or not HTTP redirects (3xx) should
  114. * be automatically followed.
  115. *
  116. * @return <code>true</code> if HTTP redirects should
  117. * be automatically followed, <tt>false</tt> if not.
  118. * @see #setFollowRedirects(boolean)
  119. */
  120. public static boolean getFollowRedirects() {
  121. return followRedirects;
  122. }
  123. /**
  124. * Sets whether HTTP redirects (requests with response code 3xx) should
  125. * be automatically followed by this <code>HttpURLConnection</code>
  126. * instance.
  127. * <p>
  128. * The default value comes from followRedirects, which defaults to
  129. * true.
  130. *
  131. * @param followRedirects a <code>boolean</code> indicating
  132. * whether or not to follow HTTP redirects.
  133. *
  134. * @see java.net.HttpURLConnection#instanceFollowRedirects
  135. * @see #getInstanceFollowRedirects
  136. */
  137. public void setInstanceFollowRedirects(boolean followRedirects) {
  138. instanceFollowRedirects = followRedirects;
  139. }
  140. /**
  141. * Returns the value of this <code>HttpURLConnection</code>'s
  142. * <code>instanceFollowRedirects</code> field.
  143. *
  144. * @return the value of this <code>HttpURLConnection</code>'s
  145. * <code>instanceFollowRedirects</code> field.
  146. * @see java.net.HttpURLConnection#instanceFollowRedirects
  147. * @see #setInstanceFollowRedirects(boolean)
  148. */
  149. public boolean getInstanceFollowRedirects() {
  150. return instanceFollowRedirects;
  151. }
  152. /**
  153. * Set the method for the URL request, one of:
  154. * <UL>
  155. * <LI>GET
  156. * <LI>POST
  157. * <LI>HEAD
  158. * <LI>OPTIONS
  159. * <LI>PUT
  160. * <LI>DELETE
  161. * <LI>TRACE
  162. * </UL> are legal, subject to protocol restrictions. The default
  163. * method is GET.
  164. *
  165. * @param method the HTTP method
  166. * @exception ProtocolException if the method cannot be reset or if
  167. * the requested method isn't valid for HTTP.
  168. * @see #getRequestMethod()
  169. */
  170. public void setRequestMethod(String method) throws ProtocolException {
  171. if (connected) {
  172. throw new ProtocolException("Can't reset method: already connected");
  173. }
  174. // This restriction will prevent people from using this class to
  175. // experiment w/ new HTTP methods using java. But it should
  176. // be placed for security - the request String could be
  177. // arbitrarily long.
  178. for (int i = 0; i < methods.length; i++) {
  179. if (methods[i].equals(method)) {
  180. this.method = method;
  181. return;
  182. }
  183. }
  184. throw new ProtocolException("Invalid HTTP method: " + method);
  185. }
  186. /**
  187. * Get the request method.
  188. * @return the HTTP request method
  189. * @see #setRequestMethod(java.lang.String)
  190. */
  191. public String getRequestMethod() {
  192. return method;
  193. }
  194. /**
  195. * Gets HTTP response status from responses like:
  196. * <PRE>
  197. * HTTP/1.0 200 OK
  198. * HTTP/1.0 401 Unauthorized
  199. * </PRE>
  200. * Extracts the ints 200 and 401 respectively.
  201. * Returns -1 if none can be discerned
  202. * from the response (i.e., the response is not valid HTTP).
  203. * @throws IOException if an error occurred connecting to the server.
  204. * @return the HTTP Status-Code
  205. */
  206. public int getResponseCode() throws IOException {
  207. if (responseCode != -1) {
  208. return responseCode;
  209. }
  210. // make sure we've gotten the headers
  211. getInputStream();
  212. String resp = getHeaderField(0);
  213. /* should have no leading/trailing LWS
  214. * expedite the typical case by assuming it has
  215. * form "HTTP/1.x <WS> 2XX <mumble>"
  216. */
  217. int ind;
  218. try {
  219. ind = resp.indexOf(' ');
  220. while(resp.charAt(ind) == ' ')
  221. ind++;
  222. responseCode = Integer.parseInt(resp.substring(ind, ind + 3));
  223. responseMessage = resp.substring(ind + 4).trim();
  224. return responseCode;
  225. } catch (Exception e) {
  226. return responseCode;
  227. }
  228. }
  229. /**
  230. * Gets the HTTP response message, if any, returned along with the
  231. * response code from a server. From responses like:
  232. * <PRE>
  233. * HTTP/1.0 200 OK
  234. * HTTP/1.0 404 Not Found
  235. * </PRE>
  236. * Extracts the Strings "OK" and "Not Found" respectively.
  237. * Returns null if none could be discerned from the responses
  238. * (the result was not valid HTTP).
  239. * @throws IOException if an error occurred connecting to the server.
  240. * @return the HTTP response message, or <code>null</code>
  241. */
  242. public String getResponseMessage() throws IOException {
  243. getResponseCode();
  244. return responseMessage;
  245. }
  246. public long getHeaderFieldDate(String name, long Default) {
  247. try {
  248. String dateString = getHeaderField(name);
  249. dateString.trim();
  250. if (dateString.indexOf("GMT") == -1) {
  251. dateString = dateString+" GMT";
  252. }
  253. return Date.parse(dateString);
  254. } catch (ThreadDeath td) {
  255. throw td;
  256. } catch(Throwable t) {
  257. }
  258. return Default;
  259. }
  260. /**
  261. * Indicates that other requests to the server
  262. * are unlikely in the near future. Calling disconnect()
  263. * should not imply that this HttpURLConnection
  264. * instance can be reused for other requests.
  265. */
  266. public abstract void disconnect();
  267. /**
  268. * Indicates if the connection is going through a proxy.
  269. * @return a boolean indicating if the connection is
  270. * using a proxy.
  271. */
  272. public abstract boolean usingProxy();
  273. public Permission getPermission() throws IOException {
  274. int port = url.getPort();
  275. port = port < 0 ? 80 : port;
  276. String host = url.getHost() + ":" + port;
  277. Permission permission = new SocketPermission(host, "connect");
  278. return permission;
  279. }
  280. /**
  281. * Returns the error stream if the connection failed
  282. * but the server sent useful data nonetheless. The
  283. * typical example is when an HTTP server responds
  284. * with a 404, which will cause a FileNotFoundException
  285. * to be thrown in connect, but the server sent an HTML
  286. * help page with suggestions as to what to do.
  287. *
  288. * <p>This method will not cause a connection to be initiated.
  289. * If there the connection was not connected, or if the server
  290. * did not have an error while connecting or if the server did
  291. * have an error but there no error data was sent, this method
  292. * will return null. This is the default.
  293. *
  294. * @return an error stream if any, null if there have been
  295. * no errors, the connection is not connected or the server
  296. * sent no useful data.
  297. */
  298. public InputStream getErrorStream() {
  299. return null;
  300. }
  301. /**
  302. * The response codes for HTTP, as of version 1.1.
  303. */
  304. // REMIND: do we want all these??
  305. // Others not here that we do want??
  306. /* 2XX: generally "OK" */
  307. /**
  308. * HTTP Status-Code 200: OK.
  309. */
  310. public static final int HTTP_OK = 200;
  311. /**
  312. * HTTP Status-Code 201: Created.
  313. */
  314. public static final int HTTP_CREATED = 201;
  315. /**
  316. * HTTP Status-Code 202: Accepted.
  317. */
  318. public static final int HTTP_ACCEPTED = 202;
  319. /**
  320. * HTTP Status-Code 203: Non-Authoritative Information.
  321. */
  322. public static final int HTTP_NOT_AUTHORITATIVE = 203;
  323. /**
  324. * HTTP Status-Code 204: No Content.
  325. */
  326. public static final int HTTP_NO_CONTENT = 204;
  327. /**
  328. * HTTP Status-Code 205: Reset Content.
  329. */
  330. public static final int HTTP_RESET = 205;
  331. /**
  332. * HTTP Status-Code 206: Partial Content.
  333. */
  334. public static final int HTTP_PARTIAL = 206;
  335. /* 3XX: relocation/redirect */
  336. /**
  337. * HTTP Status-Code 300: Multiple Choices.
  338. */
  339. public static final int HTTP_MULT_CHOICE = 300;
  340. /**
  341. * HTTP Status-Code 301: Moved Permanently.
  342. */
  343. public static final int HTTP_MOVED_PERM = 301;
  344. /**
  345. * HTTP Status-Code 302: Temporary Redirect.
  346. */
  347. public static final int HTTP_MOVED_TEMP = 302;
  348. /**
  349. * HTTP Status-Code 303: See Other.
  350. */
  351. public static final int HTTP_SEE_OTHER = 303;
  352. /**
  353. * HTTP Status-Code 304: Not Modified.
  354. */
  355. public static final int HTTP_NOT_MODIFIED = 304;
  356. /**
  357. * HTTP Status-Code 305: Use Proxy.
  358. */
  359. public static final int HTTP_USE_PROXY = 305;
  360. /* 4XX: client error */
  361. /**
  362. * HTTP Status-Code 400: Bad Request.
  363. */
  364. public static final int HTTP_BAD_REQUEST = 400;
  365. /**
  366. * HTTP Status-Code 401: Unauthorized.
  367. */
  368. public static final int HTTP_UNAUTHORIZED = 401;
  369. /**
  370. * HTTP Status-Code 402: Payment Required.
  371. */
  372. public static final int HTTP_PAYMENT_REQUIRED = 402;
  373. /**
  374. * HTTP Status-Code 403: Forbidden.
  375. */
  376. public static final int HTTP_FORBIDDEN = 403;
  377. /**
  378. * HTTP Status-Code 404: Not Found.
  379. */
  380. public static final int HTTP_NOT_FOUND = 404;
  381. /**
  382. * HTTP Status-Code 405: Method Not Allowed.
  383. */
  384. public static final int HTTP_BAD_METHOD = 405;
  385. /**
  386. * HTTP Status-Code 406: Not Acceptable.
  387. */
  388. public static final int HTTP_NOT_ACCEPTABLE = 406;
  389. /**
  390. * HTTP Status-Code 407: Proxy Authentication Required.
  391. */
  392. public static final int HTTP_PROXY_AUTH = 407;
  393. /**
  394. * HTTP Status-Code 408: Request Time-Out.
  395. */
  396. public static final int HTTP_CLIENT_TIMEOUT = 408;
  397. /**
  398. * HTTP Status-Code 409: Conflict.
  399. */
  400. public static final int HTTP_CONFLICT = 409;
  401. /**
  402. * HTTP Status-Code 410: Gone.
  403. */
  404. public static final int HTTP_GONE = 410;
  405. /**
  406. * HTTP Status-Code 411: Length Required.
  407. */
  408. public static final int HTTP_LENGTH_REQUIRED = 411;
  409. /**
  410. * HTTP Status-Code 412: Precondition Failed.
  411. */
  412. public static final int HTTP_PRECON_FAILED = 412;
  413. /**
  414. * HTTP Status-Code 413: Request Entity Too Large.
  415. */
  416. public static final int HTTP_ENTITY_TOO_LARGE = 413;
  417. /**
  418. * HTTP Status-Code 414: Request-URI Too Large.
  419. */
  420. public static final int HTTP_REQ_TOO_LONG = 414;
  421. /**
  422. * HTTP Status-Code 415: Unsupported Media Type.
  423. */
  424. public static final int HTTP_UNSUPPORTED_TYPE = 415;
  425. /* 5XX: server error */
  426. /**
  427. * @deprecated it is misplaced and shouldn't have existed.
  428. */
  429. public static final int HTTP_SERVER_ERROR = 500;
  430. /**
  431. * HTTP Status-Code 500: Internal Server Error.
  432. */
  433. public static final int HTTP_INTERNAL_ERROR = 500;
  434. /**
  435. * HTTP Status-Code 501: Not Implemented.
  436. */
  437. public static final int HTTP_NOT_IMPLEMENTED = 501;
  438. /**
  439. * HTTP Status-Code 502: Bad Gateway.
  440. */
  441. public static final int HTTP_BAD_GATEWAY = 502;
  442. /**
  443. * HTTP Status-Code 503: Service Unavailable.
  444. */
  445. public static final int HTTP_UNAVAILABLE = 503;
  446. /**
  447. * HTTP Status-Code 504: Gateway Timeout.
  448. */
  449. public static final int HTTP_GATEWAY_TIMEOUT = 504;
  450. /**
  451. * HTTP Status-Code 505: HTTP Version Not Supported.
  452. */
  453. public static final int HTTP_VERSION = 505;
  454. }