Merge "Workaround for request header values with trailing '\r' or '\r\n'"
diff --git a/Android.mk b/Android.mk
index 374a668..d98f068 100644
--- a/Android.mk
+++ b/Android.mk
@@ -51,6 +51,7 @@
 LOCAL_JAVA_LIBRARIES := core-oj core-libart conscrypt
 LOCAL_NO_STANDARD_LIBRARIES := true
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 include $(BUILD_JAVA_LIBRARY)
 
 # non-jarjar'd version of okhttp to compile the tests against
@@ -61,6 +62,7 @@
 LOCAL_JAVA_LIBRARIES := core-oj core-libart conscrypt
 LOCAL_NO_STANDARD_LIBRARIES := true
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 include $(BUILD_STATIC_JAVA_LIBRARY)
 
 include $(CLEAR_VARS)
@@ -70,6 +72,7 @@
 LOCAL_JAVA_LIBRARIES := core-oj core-libart okhttp-nojarjar junit4-target bouncycastle-nojarjar conscrypt
 LOCAL_NO_STANDARD_LIBRARIES := true
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 include $(BUILD_STATIC_JAVA_LIBRARY)
 
 ifeq ($(HOST_OS),linux)
@@ -80,5 +83,6 @@
 LOCAL_JARJAR_RULES := $(LOCAL_PATH)/jarjar-rules.txt
 LOCAL_JAVA_LIBRARIES := conscrypt-hostdex
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+LOCAL_JAVA_LANGUAGE_VERSION := 1.7
 include $(BUILD_HOST_DALVIK_JAVA_LIBRARY)
 endif  # ($(HOST_OS),linux)
diff --git a/okhttp-tests/src/test/java/com/squareup/okhttp/InterceptorTest.java b/okhttp-tests/src/test/java/com/squareup/okhttp/InterceptorTest.java
index 054343c..d8454ac 100644
--- a/okhttp-tests/src/test/java/com/squareup/okhttp/InterceptorTest.java
+++ b/okhttp-tests/src/test/java/com/squareup/okhttp/InterceptorTest.java
@@ -135,7 +135,7 @@
     Interceptor interceptor = new Interceptor() {
       @Override public Response intercept(Chain chain) throws IOException {
         Address address = chain.connection().getRoute().getAddress();
-        String sameHost = address.getUriHost();
+        String sameHost = address.getRfc2732Host();
         int differentPort = address.getUriPort() + 1;
         return chain.proceed(chain.request().newBuilder()
             .url(HttpUrl.parse("http://" + sameHost + ":" + differentPort + "/"))
diff --git a/okhttp/src/main/java/com/squareup/okhttp/Address.java b/okhttp/src/main/java/com/squareup/okhttp/Address.java
index 6f6ce08..cd3687b 100644
--- a/okhttp/src/main/java/com/squareup/okhttp/Address.java
+++ b/okhttp/src/main/java/com/squareup/okhttp/Address.java
@@ -71,7 +71,7 @@
   }
 
   /** Returns the hostname of the origin server. */
-  public String getUriHost() {
+  public String getRfc2732Host() {
     return uriHost;
   }
 
diff --git a/okhttp/src/main/java/com/squareup/okhttp/Connection.java b/okhttp/src/main/java/com/squareup/okhttp/Connection.java
index 2a3614e..a778747 100644
--- a/okhttp/src/main/java/com/squareup/okhttp/Connection.java
+++ b/okhttp/src/main/java/com/squareup/okhttp/Connection.java
@@ -222,13 +222,13 @@
     try {
       // Create the wrapper over the connected socket.
       sslSocket = (SSLSocket) sslSocketFactory.createSocket(
-          socket, address.getUriHost(), address.getUriPort(), true /* autoClose */);
+          socket, address.getRfc2732Host(), address.getUriPort(), true /* autoClose */);
 
       // Configure the socket's ciphers, TLS versions, and extensions.
       ConnectionSpec connectionSpec = connectionSpecSelector.configureSecureSocket(sslSocket);
       if (connectionSpec.supportsTlsExtensions()) {
         Platform.get().configureTlsExtensions(
-            sslSocket, address.getUriHost(), address.getProtocols());
+            sslSocket, address.getRfc2732Host(), address.getProtocols());
       }
 
       // Force handshake. This can throw!
@@ -236,16 +236,16 @@
       Handshake unverifiedHandshake = Handshake.get(sslSocket.getSession());
 
       // Verify that the socket's certificates are acceptable for the target host.
-      if (!address.getHostnameVerifier().verify(address.getUriHost(), sslSocket.getSession())) {
+      if (!address.getHostnameVerifier().verify(address.getRfc2732Host(), sslSocket.getSession())) {
         X509Certificate cert = (X509Certificate) unverifiedHandshake.peerCertificates().get(0);
-        throw new SSLPeerUnverifiedException("Hostname " + address.getUriHost() + " not verified:"
+        throw new SSLPeerUnverifiedException("Hostname " + address.getRfc2732Host() + " not verified:"
             + "\n    certificate: " + CertificatePinner.pin(cert)
             + "\n    DN: " + cert.getSubjectDN().getName()
             + "\n    subjectAltNames: " + OkHostnameVerifier.allSubjectAltNames(cert));
       }
 
       // Check that the certificate pinner is satisfied by the certificates presented.
-      address.getCertificatePinner().check(address.getUriHost(),
+      address.getCertificatePinner().check(address.getRfc2732Host(),
           unverifiedHandshake.peerCertificates());
 
       // Success! Save the handshake and the ALPN protocol.
@@ -282,7 +282,7 @@
     HttpConnection tunnelConnection = new HttpConnection(pool, this, socket);
     tunnelConnection.setTimeouts(readTimeout, writeTimeout);
     HttpUrl url = tunnelRequest.httpUrl();
-    String requestLine = "CONNECT " + url.host() + ":" + url.port() + " HTTP/1.1";
+    String requestLine = "CONNECT " + url.rfc2732host() + ":" + url.port() + " HTTP/1.1";
     while (true) {
       tunnelConnection.writeRequest(tunnelRequest.headers(), requestLine);
       tunnelConnection.flush();
diff --git a/okhttp/src/main/java/com/squareup/okhttp/HttpUrl.java b/okhttp/src/main/java/com/squareup/okhttp/HttpUrl.java
index dcc2596..0919b91 100644
--- a/okhttp/src/main/java/com/squareup/okhttp/HttpUrl.java
+++ b/okhttp/src/main/java/com/squareup/okhttp/HttpUrl.java
@@ -388,6 +388,19 @@
   }
 
   /**
+   * Same as {@link #host} except that literal IPv6 addresses are surrounding by square
+   * braces. For example, this method will return {@code [::1]} where {@code host} returns
+   * {@code ::1}.
+   */
+  public String rfc2732host() {
+    if (host.indexOf(':') == -1) {
+      return host;
+    }
+
+    return "[" + host + "]";
+  }
+
+  /**
    * Returns the explicitly-specified port if one was provided, or the default port for this URL's
    * scheme. For example, this returns 8443 for {@code https://square.com:8443/} and 443 for {@code
    * https://square.com/}. The result is in {@code [1..65535]}.
diff --git a/okhttp/src/main/java/com/squareup/okhttp/internal/Util.java b/okhttp/src/main/java/com/squareup/okhttp/internal/Util.java
index efc26ec..4000fbe 100644
--- a/okhttp/src/main/java/com/squareup/okhttp/internal/Util.java
+++ b/okhttp/src/main/java/com/squareup/okhttp/internal/Util.java
@@ -259,8 +259,8 @@
   public static String hostHeader(HttpUrl url) {
     // TODO: square braces for IPv6 ?
     return url.port() != HttpUrl.defaultPort(url.scheme())
-        ? url.host() + ":" + url.port()
-        : url.host();
+        ? url.rfc2732host() + ":" + url.port()
+        : url.rfc2732host();
   }
 
   /** Returns {@code s} with control characters and non-ASCII characters replaced with '?'. */
diff --git a/okhttp/src/main/java/com/squareup/okhttp/internal/http/AuthenticatorAdapter.java b/okhttp/src/main/java/com/squareup/okhttp/internal/http/AuthenticatorAdapter.java
index 8d88410..a9f9b5a 100644
--- a/okhttp/src/main/java/com/squareup/okhttp/internal/http/AuthenticatorAdapter.java
+++ b/okhttp/src/main/java/com/squareup/okhttp/internal/http/AuthenticatorAdapter.java
@@ -43,7 +43,7 @@
       if (!"Basic".equalsIgnoreCase(challenge.getScheme())) continue;
 
       PasswordAuthentication auth = java.net.Authenticator.requestPasswordAuthentication(
-          url.host(), getConnectToInetAddress(proxy, url), url.port(), url.scheme(),
+          url.rfc2732host(), getConnectToInetAddress(proxy, url), url.port(), url.scheme(),
           challenge.getRealm(), challenge.getScheme(), url.url(), RequestorType.SERVER);
       if (auth == null) continue;
 
diff --git a/okhttp/src/main/java/com/squareup/okhttp/internal/http/HttpEngine.java b/okhttp/src/main/java/com/squareup/okhttp/internal/http/HttpEngine.java
index 70eeaaa..7286428 100644
--- a/okhttp/src/main/java/com/squareup/okhttp/internal/http/HttpEngine.java
+++ b/okhttp/src/main/java/com/squareup/okhttp/internal/http/HttpEngine.java
@@ -848,7 +848,7 @@
         Address address = connection().getRoute().getAddress();
 
         // Confirm that the interceptor uses the connection we've already prepared.
-        if (!request.httpUrl().host().equals(address.getUriHost())
+        if (!request.httpUrl().rfc2732host().equals(address.getRfc2732Host())
             || request.httpUrl().port() != address.getUriPort()) {
           throw new IllegalStateException("network interceptor " + caller
               + " must retain the same host and port");
@@ -1135,7 +1135,7 @@
       certificatePinner = client.getCertificatePinner();
     }
 
-    return new Address(request.httpUrl().host(), request.httpUrl().port(),
+    return new Address(request.httpUrl().rfc2732host(), request.httpUrl().port(),
         client.getSocketFactory(), sslSocketFactory, hostnameVerifier, certificatePinner,
         client.getAuthenticator(), client.getProxy(), client.getProtocols(),
         client.getConnectionSpecs(), client.getProxySelector());
diff --git a/okhttp/src/main/java/com/squareup/okhttp/internal/http/RouteSelector.java b/okhttp/src/main/java/com/squareup/okhttp/internal/http/RouteSelector.java
index b16bab3..b210c56 100644
--- a/okhttp/src/main/java/com/squareup/okhttp/internal/http/RouteSelector.java
+++ b/okhttp/src/main/java/com/squareup/okhttp/internal/http/RouteSelector.java
@@ -149,7 +149,7 @@
   /** Returns the next proxy to try. May be PROXY.NO_PROXY but never null. */
   private Proxy nextProxy() throws IOException {
     if (!hasNextProxy()) {
-      throw new SocketException("No route to " + address.getUriHost()
+      throw new SocketException("No route to " + address.getRfc2732Host()
           + "; exhausted proxy configurations: " + proxies);
     }
     Proxy result = proxies.get(nextProxyIndex++);
@@ -165,7 +165,7 @@
     String socketHost;
     int socketPort;
     if (proxy.type() == Proxy.Type.DIRECT || proxy.type() == Proxy.Type.SOCKS) {
-      socketHost = address.getUriHost();
+      socketHost = address.getRfc2732Host();
       socketPort = address.getUriPort();
     } else {
       SocketAddress proxyAddress = proxy.address();
@@ -217,7 +217,7 @@
   /** Returns the next socket address to try. */
   private InetSocketAddress nextInetSocketAddress() throws IOException {
     if (!hasNextInetSocketAddress()) {
-      throw new SocketException("No route to " + address.getUriHost()
+      throw new SocketException("No route to " + address.getRfc2732Host()
           + "; exhausted inet socket addresses: " + inetSocketAddresses);
     }
     return inetSocketAddresses.get(nextInetSocketAddressIndex++);