/* HttpUtil.java Copyright (c) 2017 NTT DOCOMO,INC. Released under the MIT license http://opensource.org/licenses/mit-license.php */ package org.deviceconnect.android.manager.util; import android.os.Build; import android.util.Log; import org.deviceconnect.android.manager.BuildConfig; import java.io.ByteArrayOutputStream; 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 javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.KeyManager; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; public final class HttpUtil { /** * デバック用フラグ. */ private static final boolean DEBUG = BuildConfig.DEBUG; /** * デバック用タグを定義します. */ private static final String TAG = "DConnect"; /** * バッファサイズを定義します. */ private static final int BUF_SIZE = 4096; /** * エラーとなるレスポンスコードを定義します. */ private static final int ERROR_RESPONSE_CODE = 400; /** * 接続のタイムアウト. */ private static final int CONNECT_TIMEOUT = 10 * 1000; /** * 読み込みのタイムアウト時間. */ private static final int READ_TIMEOUT = 30 * 1000; /** * POSTメソッドを定義します. */ private static final String METHOD_POST = "POST"; /** * PUTメソッドを定義します. */ private static final String METHOD_PUT = "PUT"; /** * GETメソッドを定義します. */ private static final String METHOD_GET = "GET"; /** * コンストラクタ. * ユーティリティクラスなので、インスタンスは作成させない。 */ private HttpUtil() { } private static byte[] connect(String method, String uri, Map<String, String> headers, String body) { if (DEBUG) { Log.d(TAG, "connect: method=" + method + " uri=" + uri); if (headers != null) { for (String key : headers.keySet()) { Log.d(TAG, "header: " + key + "=" + headers.get(key)); } } if (body != null) { Log.d(TAG, "body: " + body); } } ByteArrayOutputStream baos = new ByteArrayOutputStream(); HttpURLConnection conn = null; try { if (uri.startsWith("https://")) { conn = makeHttpsURLConnection(new URL(uri)); } else { conn = (HttpURLConnection) new URL(uri).openConnection(); } conn.setConnectTimeout(CONNECT_TIMEOUT); conn.setReadTimeout(READ_TIMEOUT); conn.setRequestMethod(method); conn.setDoInput(true); conn.setDoOutput(METHOD_POST.equals(method)); if (headers != null) { for (String key : headers.keySet()) { conn.setRequestProperty(key, headers.get(key)); } } // 4.x系はkeep-aliveを行うと例外が発生するため、offにする // 参考: http://osa030.hatenablog.com/entry/2015/05/22/181155 if (Build.VERSION.SDK_INT > 13 && Build.VERSION.SDK_INT < 19) { conn.setRequestProperty("Connection", "close"); } conn.setRequestProperty("Origin", "http://localhost"); conn.connect(); if (body != null && (METHOD_POST.equals(method) || METHOD_PUT.equals(method))) { OutputStream os = conn.getOutputStream(); os.write(body.getBytes()); os.flush(); os.close(); } int resp = conn.getResponseCode(); if (DEBUG) { Log.d(TAG, "response code=" + resp); } if (resp < ERROR_RESPONSE_CODE) { InputStream in = conn.getInputStream(); int len; byte[] buf = new byte[BUF_SIZE]; while ((len = in.read(buf)) > 0) { baos.write(buf, 0, len); } in.close(); } else { if (DEBUG) { Log.w(TAG, "Failed to connect the server. response=" + resp); } return null; } } catch (IOException e) { if (DEBUG) { Log.e(TAG, "Failed to connect the server.", e); } return null; } catch (Exception e) { if (DEBUG) { Log.e(TAG, "Failed to connect the server.", e); } return null; } catch (OutOfMemoryError e) { if (DEBUG) { Log.e(TAG, "Failed to connect the server.", e); } return null; } finally { if (conn != null) { conn.disconnect(); } } return baos.toByteArray(); } public static byte[] get(final String uri) { return connect(METHOD_GET, uri, null, null); } private static HttpsURLConnection makeHttpsURLConnection(final URL url) throws IOException, NoSuchAlgorithmException, KeyManagementException { HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); connection.setHostnameVerifier(new HostnameVerifier() { @Override public boolean verify(final String hostname, final SSLSession sslSession) { return true; } }); KeyManager[] keyManagers = null; TrustManager[] transManagers = { new X509TrustManager() { @Override public void checkClientTrusted(final X509Certificate[] chain, final String authType) throws CertificateException { } @Override public void checkServerTrusted(final X509Certificate[] chain, final String authType) throws CertificateException { } @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } } }; SSLContext sslcontext = SSLContext.getInstance("SSL"); sslcontext.init(keyManagers, transManagers, new SecureRandom()); connection.setSSLSocketFactory(sslcontext.getSocketFactory()); return connection; } }