jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java
changeset 479 c6ddcfc7ff4d
parent 478 5adf3e3f1ff3
child 715 f16baef3a20e
equal deleted inserted replaced
478:5adf3e3f1ff3 479:c6ddcfc7ff4d
    73 
    73 
    74 public class HttpURLConnection extends java.net.HttpURLConnection {
    74 public class HttpURLConnection extends java.net.HttpURLConnection {
    75 
    75 
    76     private static Logger logger = Logger.getLogger("sun.net.www.protocol.http.HttpURLConnection");
    76     private static Logger logger = Logger.getLogger("sun.net.www.protocol.http.HttpURLConnection");
    77 
    77 
       
    78     static String HTTP_CONNECT = "CONNECT";
       
    79 
    78     static final String version;
    80     static final String version;
    79     public static final String userAgent;
    81     public static final String userAgent;
    80 
    82 
    81     /* max # of allowed re-directs */
    83     /* max # of allowed re-directs */
    82     static final int defaultmaxRedirects = 20;
    84     static final int defaultmaxRedirects = 20;
   264     private Exception rememberedException = null;
   266     private Exception rememberedException = null;
   265 
   267 
   266     /* If we decide we want to reuse a client, we put it here */
   268     /* If we decide we want to reuse a client, we put it here */
   267     private HttpClient reuseClient = null;
   269     private HttpClient reuseClient = null;
   268 
   270 
       
   271     /* Tunnel states */
       
   272     enum TunnelState {
       
   273         /* No tunnel */
       
   274         NONE,
       
   275 
       
   276         /* Setting up a tunnel */
       
   277         SETUP,
       
   278 
       
   279         /* Tunnel has been successfully setup */
       
   280         TUNNELING
       
   281     }
       
   282 
       
   283     private TunnelState tunnelState = TunnelState.NONE;
       
   284 
   269     /* Redefine timeouts from java.net.URLConnection as we nee -1 to mean
   285     /* Redefine timeouts from java.net.URLConnection as we nee -1 to mean
   270      * not set. This is to ensure backward compatibility.
   286      * not set. This is to ensure backward compatibility.
   271      */
   287      */
   272     private int connectTimeout = -1;
   288     private int connectTimeout = -1;
   273     private int readTimeout = -1;
   289     private int readTimeout = -1;
   336         /* print all message headers in the MessageHeader
   352         /* print all message headers in the MessageHeader
   337          * onto the wire - all the ones we've set and any
   353          * onto the wire - all the ones we've set and any
   338          * others that have been set
   354          * others that have been set
   339          */
   355          */
   340         // send any pre-emptive authentication
   356         // send any pre-emptive authentication
   341         if (http.usingProxy) {
   357         if (http.usingProxy && tunnelState() != TunnelState.TUNNELING) {
   342             setPreemptiveProxyAuthentication(requests);
   358             setPreemptiveProxyAuthentication(requests);
   343         }
   359         }
   344         if (!setRequests) {
   360         if (!setRequests) {
   345 
   361 
   346             /* We're very particular about the order in which we
   362             /* We're very particular about the order in which we
  1402         if ((proxyAuthentication != null )&& ! (proxyAuthentication instanceof
  1418         if ((proxyAuthentication != null )&& ! (proxyAuthentication instanceof
  1403                                                         NTLMAuthentication)) {
  1419                                                         NTLMAuthentication)) {
  1404             String raw = auth.raw();
  1420             String raw = auth.raw();
  1405             if (proxyAuthentication.isAuthorizationStale (raw)) {
  1421             if (proxyAuthentication.isAuthorizationStale (raw)) {
  1406                 /* we can retry with the current credentials */
  1422                 /* we can retry with the current credentials */
  1407                 requests.set (proxyAuthentication.getHeaderName(),
  1423                 String value;
  1408                               proxyAuthentication.getHeaderValue(
  1424                 if (tunnelState() == TunnelState.SETUP &&
  1409                                                      url, method));
  1425                       proxyAuthentication instanceof DigestAuthentication) {
       
  1426                     value = ((DigestAuthentication)proxyAuthentication)
       
  1427                             .getHeaderValue(connectRequestURI(url), HTTP_CONNECT);
       
  1428                 } else {
       
  1429                     value = proxyAuthentication.getHeaderValue(url, method);
       
  1430                 }
       
  1431                 requests.set(proxyAuthentication.getHeaderName(), value);
  1410                 currentProxyCredentials = proxyAuthentication;
  1432                 currentProxyCredentials = proxyAuthentication;
  1411                 return  proxyAuthentication;
  1433                 return proxyAuthentication;
  1412             } else {
  1434             } else {
  1413                 proxyAuthentication.removeFromCache();
  1435                 proxyAuthentication.removeFromCache();
  1414             }
  1436             }
  1415         }
  1437         }
  1416         proxyAuthentication = getHttpProxyAuthentication(auth);
  1438         proxyAuthentication = getHttpProxyAuthentication(auth);
  1417         currentProxyCredentials = proxyAuthentication;
  1439         currentProxyCredentials = proxyAuthentication;
  1418         return  proxyAuthentication;
  1440         return  proxyAuthentication;
       
  1441     }
       
  1442 
       
  1443     /**
       
  1444      * Returns the tunnel state.
       
  1445      *
       
  1446      * @return  the state
       
  1447      */
       
  1448     TunnelState tunnelState() {
       
  1449         return tunnelState;
       
  1450     }
       
  1451 
       
  1452     /**
       
  1453      * Set the tunneling status.
       
  1454      *
       
  1455      * @param  the state
       
  1456      */
       
  1457     void setTunnelState(TunnelState tunnelState) {
       
  1458         this.tunnelState = tunnelState;
  1419     }
  1459     }
  1420 
  1460 
  1421     /**
  1461     /**
  1422      * establish a tunnel through proxy server
  1462      * establish a tunnel through proxy server
  1423      */
  1463      */
  1435 
  1475 
  1436         // Read comments labeled "Failed Negotiate" for details.
  1476         // Read comments labeled "Failed Negotiate" for details.
  1437         boolean inNegotiateProxy = false;
  1477         boolean inNegotiateProxy = false;
  1438 
  1478 
  1439         try {
  1479         try {
       
  1480             /* Actively setting up a tunnel */
       
  1481             setTunnelState(TunnelState.SETUP);
       
  1482 
  1440             do {
  1483             do {
  1441                 if (!checkReuseConnection()) {
  1484                 if (!checkReuseConnection()) {
  1442                     proxiedConnect(url, proxyHost, proxyPort, false);
  1485                     proxiedConnect(url, proxyHost, proxyPort, false);
  1443                 }
  1486                 }
  1444                 // send the "CONNECT" request to establish a tunnel
  1487                 // send the "CONNECT" request to establish a tunnel
  1510                     // cache auth info on success, domain header not relevant.
  1553                     // cache auth info on success, domain header not relevant.
  1511                     proxyAuthentication.addToCache();
  1554                     proxyAuthentication.addToCache();
  1512                 }
  1555                 }
  1513 
  1556 
  1514                 if (respCode == HTTP_OK) {
  1557                 if (respCode == HTTP_OK) {
       
  1558                     setTunnelState(TunnelState.TUNNELING);
  1515                     break;
  1559                     break;
  1516                 }
  1560                 }
  1517                 // we don't know how to deal with other response code
  1561                 // we don't know how to deal with other response code
  1518                 // so disconnect and report error
  1562                 // so disconnect and report error
  1519                 disconnectInternal();
  1563                 disconnectInternal();
       
  1564                 setTunnelState(TunnelState.NONE);
  1520                 break;
  1565                 break;
  1521             } while (retryTunnel < maxRedirects);
  1566             } while (retryTunnel < maxRedirects);
  1522 
  1567 
  1523             if (retryTunnel >= maxRedirects || (respCode != HTTP_OK)) {
  1568             if (retryTunnel >= maxRedirects || (respCode != HTTP_OK)) {
  1524                 throw new IOException("Unable to tunnel through proxy."+
  1569                 throw new IOException("Unable to tunnel through proxy."+
  1534         // restore original request headers
  1579         // restore original request headers
  1535         requests = savedRequests;
  1580         requests = savedRequests;
  1536 
  1581 
  1537         // reset responses
  1582         // reset responses
  1538         responses.reset();
  1583         responses.reset();
       
  1584     }
       
  1585 
       
  1586     static String connectRequestURI(URL url) {
       
  1587         String host = url.getHost();
       
  1588         int port = url.getPort();
       
  1589         port = port != -1 ? port : url.getDefaultPort();
       
  1590 
       
  1591         return host + ":" + port;
  1539     }
  1592     }
  1540 
  1593 
  1541     /**
  1594     /**
  1542      * send a CONNECT request for establishing a tunnel to proxy server
  1595      * send a CONNECT request for establishing a tunnel to proxy server
  1543      */
  1596      */
  1549         // so the first one must be the http method (GET, etc.).
  1602         // so the first one must be the http method (GET, etc.).
  1550         // we need to set it to CONNECT soon, remove this one first.
  1603         // we need to set it to CONNECT soon, remove this one first.
  1551         // otherwise, there may have 2 http methods in headers
  1604         // otherwise, there may have 2 http methods in headers
  1552         if (setRequests) requests.set(0, null, null);
  1605         if (setRequests) requests.set(0, null, null);
  1553 
  1606 
  1554         requests.prepend("CONNECT " + url.getHost() + ":"
  1607         requests.prepend(HTTP_CONNECT + " " + connectRequestURI(url)
  1555                          + (port != -1 ? port : url.getDefaultPort())
       
  1556                          + " " + httpVersion, null);
  1608                          + " " + httpVersion, null);
  1557         requests.setIfNotSet("User-Agent", userAgent);
  1609         requests.setIfNotSet("User-Agent", userAgent);
  1558 
  1610 
  1559         String host = url.getHost();
  1611         String host = url.getHost();
  1560         if (port != -1 && port != url.getDefaultPort()) {
  1612         if (port != -1 && port != url.getDefaultPort()) {
  1581     private void setPreemptiveProxyAuthentication(MessageHeader requests) {
  1633     private void setPreemptiveProxyAuthentication(MessageHeader requests) {
  1582         AuthenticationInfo pauth
  1634         AuthenticationInfo pauth
  1583             = AuthenticationInfo.getProxyAuth(http.getProxyHostUsed(),
  1635             = AuthenticationInfo.getProxyAuth(http.getProxyHostUsed(),
  1584                                               http.getProxyPortUsed());
  1636                                               http.getProxyPortUsed());
  1585         if (pauth != null && pauth.supportsPreemptiveAuthorization()) {
  1637         if (pauth != null && pauth.supportsPreemptiveAuthorization()) {
       
  1638             String value;
       
  1639             if (tunnelState() == TunnelState.SETUP &&
       
  1640                     pauth instanceof DigestAuthentication) {
       
  1641                 value = ((DigestAuthentication)pauth)
       
  1642                         .getHeaderValue(connectRequestURI(url), HTTP_CONNECT);
       
  1643             } else {
       
  1644                 value = pauth.getHeaderValue(url, method);
       
  1645             }
       
  1646 
  1586             // Sets "Proxy-authorization"
  1647             // Sets "Proxy-authorization"
  1587             requests.set(pauth.getHeaderName(),
  1648             requests.set(pauth.getHeaderName(), value);
  1588                                  pauth.getHeaderValue(url,method));
       
  1589             currentProxyCredentials = pauth;
  1649             currentProxyCredentials = pauth;
  1590         }
  1650         }
  1591     }
  1651     }
  1592 
  1652 
  1593     /**
  1653     /**