co.cask.common.http.HttpRequests Maven / Gradle / Ivy
/*
* Copyright © 2014 Cask Data, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package co.cask.common.http;
import com.google.common.collect.Multimap;
import com.google.common.io.ByteStreams;
import com.google.common.io.InputSupplier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
/**
* Executes {@link HttpRequest}s and returns an {@link HttpResponse}.
*/
public final class HttpRequests {
private static final Logger LOG = LoggerFactory.getLogger(HttpRequests.class);
private static final AtomicReference TRUST_ALL_SSL_FACTORY =
new AtomicReference();
private HttpRequests() { }
/**
* Executes an HTTP request to the url provided.
*
* @param request HTTP request to execute
* @param requestConfig configuration for the HTTP request to execute
* @return HTTP response
*/
public static HttpResponse execute(HttpRequest request, HttpRequestConfig requestConfig) throws IOException {
String requestMethod = request.getMethod().name();
URL url = request.getURL();
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod(requestMethod);
conn.setReadTimeout(requestConfig.getReadTimeout());
conn.setConnectTimeout(requestConfig.getConnectTimeout());
Multimap headers = request.getHeaders();
if (headers != null && !headers.isEmpty()) {
for (Map.Entry header : headers.entries()) {
conn.setRequestProperty(header.getKey(), header.getValue());
}
}
InputSupplier extends InputStream> bodySrc = request.getBody();
if (bodySrc != null) {
conn.setDoOutput(true);
Long bodyLength = request.getBodyLength();
if (bodyLength != null) {
// use intValue to support 1.6
if (bodyLength > requestConfig.getFixedLengthStreamingThreshold()) {
conn.setFixedLengthStreamingMode(bodyLength.intValue());
}
} else {
conn.setChunkedStreamingMode(0);
}
}
if (conn instanceof HttpsURLConnection && !requestConfig.isVerifySSLCert()) {
// Certificate checks are disabled for HTTPS connection.
LOG.debug("Disabling SSL certificate check for {}", request.getURL());
try {
disableCertCheck((HttpsURLConnection) conn);
} catch (Exception e) {
LOG.error("Got exception while disabling SSL certificate check for {}", request.getURL());
}
}
conn.connect();
try {
if (bodySrc != null) {
OutputStream os = conn.getOutputStream();
try {
ByteStreams.copy(bodySrc, os);
} finally {
os.close();
}
}
try {
if (isSuccessful(conn.getResponseCode())) {
return new HttpResponse(conn.getResponseCode(), conn.getResponseMessage(),
ByteStreams.toByteArray(conn.getInputStream()), conn.getHeaderFields());
}
} catch (FileNotFoundException e) {
// Server returns 404. Hence handle as error flow below. Intentional having empty catch block.
}
// Non 2xx response
InputStream es = conn.getErrorStream();
byte[] content = (es == null) ? new byte[0] : ByteStreams.toByteArray(es);
return new HttpResponse(conn.getResponseCode(), conn.getResponseMessage(), content, conn.getHeaderFields());
} finally {
conn.disconnect();
}
}
/**
* Executes an HTTP request with default request configuration.
*
* @param request HTTP request to execute
* @return HTTP response
* @throws java.io.IOException
*/
public static HttpResponse execute(HttpRequest request) throws IOException {
return execute(request, HttpRequestConfig.DEFAULT);
}
private static boolean isSuccessful(int responseCode) {
return 200 <= responseCode && responseCode < 300;
}
public static void disableCertCheck(HttpsURLConnection conn)
throws NoSuchAlgorithmException, KeyManagementException {
if (TRUST_ALL_SSL_FACTORY.get() == null) {
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, new TrustManager[]{
new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s)
throws CertificateException {
// Trust all
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s)
throws CertificateException {
// Trust all
}
}
}, new SecureRandom());
TRUST_ALL_SSL_FACTORY.compareAndSet(null, sslContext.getSocketFactory());
}
conn.setSSLSocketFactory(TRUST_ALL_SSL_FACTORY.get());
conn.setHostnameVerifier(TRUST_ALL_HOSTNAME_VERIFIER);
}
private static final HostnameVerifier TRUST_ALL_HOSTNAME_VERIFIER =
new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
}