1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17package com.squareup.okhttp.internal.http; 18 19import com.squareup.okhttp.OkHttpClient; 20import java.io.IOException; 21import java.io.InputStream; 22import java.io.OutputStream; 23import java.net.HttpURLConnection; 24import java.net.ProtocolException; 25import java.net.SecureCacheResponse; 26import java.net.URL; 27import java.security.Permission; 28import java.security.Principal; 29import java.security.cert.Certificate; 30import java.util.List; 31import java.util.Map; 32import javax.net.ssl.HostnameVerifier; 33import javax.net.ssl.HttpsURLConnection; 34import javax.net.ssl.SSLPeerUnverifiedException; 35import javax.net.ssl.SSLSocket; 36import javax.net.ssl.SSLSocketFactory; 37 38public final class HttpsURLConnectionImpl extends HttpsURLConnection { 39 40 /** HttpUrlConnectionDelegate allows reuse of HttpURLConnectionImpl. */ 41 private final HttpUrlConnectionDelegate delegate; 42 43 public HttpsURLConnectionImpl(URL url, OkHttpClient client) { 44 super(url); 45 delegate = new HttpUrlConnectionDelegate(url, client); 46 } 47 48 @Override public String getCipherSuite() { 49 SecureCacheResponse cacheResponse = delegate.getSecureCacheResponse(); 50 if (cacheResponse != null) { 51 return cacheResponse.getCipherSuite(); 52 } 53 SSLSocket sslSocket = getSslSocket(); 54 if (sslSocket != null) { 55 return sslSocket.getSession().getCipherSuite(); 56 } 57 return null; 58 } 59 60 @Override public Certificate[] getLocalCertificates() { 61 SecureCacheResponse cacheResponse = delegate.getSecureCacheResponse(); 62 if (cacheResponse != null) { 63 List<Certificate> result = cacheResponse.getLocalCertificateChain(); 64 return result != null ? result.toArray(new Certificate[result.size()]) : null; 65 } 66 SSLSocket sslSocket = getSslSocket(); 67 if (sslSocket != null) { 68 return sslSocket.getSession().getLocalCertificates(); 69 } 70 return null; 71 } 72 73 @Override public Certificate[] getServerCertificates() throws SSLPeerUnverifiedException { 74 SecureCacheResponse cacheResponse = delegate.getSecureCacheResponse(); 75 if (cacheResponse != null) { 76 List<Certificate> result = cacheResponse.getServerCertificateChain(); 77 return result != null ? result.toArray(new Certificate[result.size()]) : null; 78 } 79 SSLSocket sslSocket = getSslSocket(); 80 if (sslSocket != null) { 81 return sslSocket.getSession().getPeerCertificates(); 82 } 83 return null; 84 } 85 86 @Override public Principal getPeerPrincipal() throws SSLPeerUnverifiedException { 87 SecureCacheResponse cacheResponse = delegate.getSecureCacheResponse(); 88 if (cacheResponse != null) { 89 return cacheResponse.getPeerPrincipal(); 90 } 91 SSLSocket sslSocket = getSslSocket(); 92 if (sslSocket != null) { 93 return sslSocket.getSession().getPeerPrincipal(); 94 } 95 return null; 96 } 97 98 @Override public Principal getLocalPrincipal() { 99 SecureCacheResponse cacheResponse = delegate.getSecureCacheResponse(); 100 if (cacheResponse != null) { 101 return cacheResponse.getLocalPrincipal(); 102 } 103 SSLSocket sslSocket = getSslSocket(); 104 if (sslSocket != null) { 105 return sslSocket.getSession().getLocalPrincipal(); 106 } 107 return null; 108 } 109 110 public HttpEngine getHttpEngine() { 111 return delegate.getHttpEngine(); 112 } 113 114 private SSLSocket getSslSocket() { 115 if (delegate.httpEngine == null || !delegate.httpEngine.connected) { 116 throw new IllegalStateException("Connection has not yet been established"); 117 } 118 return delegate.httpEngine instanceof HttpsEngine 119 ? ((HttpsEngine) delegate.httpEngine).getSslSocket() 120 : null; // Not HTTPS! Probably an https:// to http:// redirect. 121 } 122 123 @Override public void disconnect() { 124 delegate.disconnect(); 125 } 126 127 @Override public InputStream getErrorStream() { 128 return delegate.getErrorStream(); 129 } 130 131 @Override public String getRequestMethod() { 132 return delegate.getRequestMethod(); 133 } 134 135 @Override public int getResponseCode() throws IOException { 136 return delegate.getResponseCode(); 137 } 138 139 @Override public String getResponseMessage() throws IOException { 140 return delegate.getResponseMessage(); 141 } 142 143 @Override public void setRequestMethod(String method) throws ProtocolException { 144 delegate.setRequestMethod(method); 145 } 146 147 @Override public boolean usingProxy() { 148 return delegate.usingProxy(); 149 } 150 151 @Override public boolean getInstanceFollowRedirects() { 152 return delegate.getInstanceFollowRedirects(); 153 } 154 155 @Override public void setInstanceFollowRedirects(boolean followRedirects) { 156 delegate.setInstanceFollowRedirects(followRedirects); 157 } 158 159 @Override public void connect() throws IOException { 160 connected = true; 161 delegate.connect(); 162 } 163 164 @Override public boolean getAllowUserInteraction() { 165 return delegate.getAllowUserInteraction(); 166 } 167 168 @Override public Object getContent() throws IOException { 169 return delegate.getContent(); 170 } 171 172 @SuppressWarnings("unchecked") // Spec does not generify 173 @Override public Object getContent(Class[] types) throws IOException { 174 return delegate.getContent(types); 175 } 176 177 @Override public String getContentEncoding() { 178 return delegate.getContentEncoding(); 179 } 180 181 @Override public int getContentLength() { 182 return delegate.getContentLength(); 183 } 184 185 @Override public String getContentType() { 186 return delegate.getContentType(); 187 } 188 189 @Override public long getDate() { 190 return delegate.getDate(); 191 } 192 193 @Override public boolean getDefaultUseCaches() { 194 return delegate.getDefaultUseCaches(); 195 } 196 197 @Override public boolean getDoInput() { 198 return delegate.getDoInput(); 199 } 200 201 @Override public boolean getDoOutput() { 202 return delegate.getDoOutput(); 203 } 204 205 @Override public long getExpiration() { 206 return delegate.getExpiration(); 207 } 208 209 @Override public String getHeaderField(int pos) { 210 return delegate.getHeaderField(pos); 211 } 212 213 @Override public Map<String, List<String>> getHeaderFields() { 214 return delegate.getHeaderFields(); 215 } 216 217 @Override public Map<String, List<String>> getRequestProperties() { 218 return delegate.getRequestProperties(); 219 } 220 221 @Override public void addRequestProperty(String field, String newValue) { 222 delegate.addRequestProperty(field, newValue); 223 } 224 225 @Override public String getHeaderField(String key) { 226 return delegate.getHeaderField(key); 227 } 228 229 @Override public long getHeaderFieldDate(String field, long defaultValue) { 230 return delegate.getHeaderFieldDate(field, defaultValue); 231 } 232 233 @Override public int getHeaderFieldInt(String field, int defaultValue) { 234 return delegate.getHeaderFieldInt(field, defaultValue); 235 } 236 237 @Override public String getHeaderFieldKey(int position) { 238 return delegate.getHeaderFieldKey(position); 239 } 240 241 @Override public long getIfModifiedSince() { 242 return delegate.getIfModifiedSince(); 243 } 244 245 @Override public InputStream getInputStream() throws IOException { 246 return delegate.getInputStream(); 247 } 248 249 @Override public long getLastModified() { 250 return delegate.getLastModified(); 251 } 252 253 @Override public OutputStream getOutputStream() throws IOException { 254 return delegate.getOutputStream(); 255 } 256 257 @Override public Permission getPermission() throws IOException { 258 return delegate.getPermission(); 259 } 260 261 @Override public String getRequestProperty(String field) { 262 return delegate.getRequestProperty(field); 263 } 264 265 @Override public URL getURL() { 266 return delegate.getURL(); 267 } 268 269 @Override public boolean getUseCaches() { 270 return delegate.getUseCaches(); 271 } 272 273 @Override public void setAllowUserInteraction(boolean newValue) { 274 delegate.setAllowUserInteraction(newValue); 275 } 276 277 @Override public void setDefaultUseCaches(boolean newValue) { 278 delegate.setDefaultUseCaches(newValue); 279 } 280 281 @Override public void setDoInput(boolean newValue) { 282 delegate.setDoInput(newValue); 283 } 284 285 @Override public void setDoOutput(boolean newValue) { 286 delegate.setDoOutput(newValue); 287 } 288 289 @Override public void setIfModifiedSince(long newValue) { 290 delegate.setIfModifiedSince(newValue); 291 } 292 293 @Override public void setRequestProperty(String field, String newValue) { 294 delegate.setRequestProperty(field, newValue); 295 } 296 297 @Override public void setUseCaches(boolean newValue) { 298 delegate.setUseCaches(newValue); 299 } 300 301 @Override public void setConnectTimeout(int timeoutMillis) { 302 delegate.setConnectTimeout(timeoutMillis); 303 } 304 305 @Override public int getConnectTimeout() { 306 return delegate.getConnectTimeout(); 307 } 308 309 @Override public void setReadTimeout(int timeoutMillis) { 310 delegate.setReadTimeout(timeoutMillis); 311 } 312 313 @Override public int getReadTimeout() { 314 return delegate.getReadTimeout(); 315 } 316 317 @Override public String toString() { 318 return delegate.toString(); 319 } 320 321 @Override public void setFixedLengthStreamingMode(int contentLength) { 322 delegate.setFixedLengthStreamingMode(contentLength); 323 } 324 325 @Override public void setChunkedStreamingMode(int chunkLength) { 326 delegate.setChunkedStreamingMode(chunkLength); 327 } 328 329 @Override public void setHostnameVerifier(HostnameVerifier hostnameVerifier) { 330 delegate.client.setHostnameVerifier(hostnameVerifier); 331 } 332 333 @Override public HostnameVerifier getHostnameVerifier() { 334 return delegate.client.getHostnameVerifier(); 335 } 336 337 @Override public void setSSLSocketFactory(SSLSocketFactory sslSocketFactory) { 338 delegate.client.setSslSocketFactory(sslSocketFactory); 339 } 340 341 @Override public SSLSocketFactory getSSLSocketFactory() { 342 return delegate.client.getSslSocketFactory(); 343 } 344 345 private final class HttpUrlConnectionDelegate extends HttpURLConnectionImpl { 346 private HttpUrlConnectionDelegate(URL url, OkHttpClient client) { 347 super(url, client); 348 } 349 350 @Override public HttpURLConnection getHttpConnectionToCache() { 351 return HttpsURLConnectionImpl.this; 352 } 353 354 public SecureCacheResponse getSecureCacheResponse() { 355 return httpEngine instanceof HttpsEngine 356 ? (SecureCacheResponse) httpEngine.getCacheResponse() 357 : null; 358 } 359 } 360} 361