001/** 002 * Copyright (c) 2015-2022, Michael Yang 杨福海 (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package io.jboot.components.http.okhttp; 017 018import io.jboot.components.http.JbootHttp; 019import io.jboot.components.http.JbootHttpRequest; 020import io.jboot.components.http.JbootHttpResponse; 021import okhttp3.*; 022 023import javax.net.ssl.*; 024import java.io.File; 025import java.security.KeyStore; 026import java.security.SecureRandom; 027import java.security.cert.X509Certificate; 028import java.util.Map; 029 030/** 031 * @author Michael Yang 杨福海 (fuhai999@gmail.com) 032 * @version V1.0 033 */ 034public class OKHttpImpl implements JbootHttp { 035 036 public OKHttpImpl() { 037 038 } 039 040 @Override 041 public JbootHttpResponse handle(JbootHttpRequest request) { 042 JbootHttpResponse response = new JbootHttpResponse(request); 043 doProcess(request, response); 044 return response; 045 } 046 047 048 private void doProcess(JbootHttpRequest request, JbootHttpResponse response) { 049 try { 050 // post 请求 或者 put 请求 051 if (request.isPostOrPutRequest()) { 052 if (request.getBodyContent() != null) { 053 request.appendParasToUrl(); 054 } 055 doProcessPostRequest(request, response); 056 } 057 058 // 其他非 post 和 put 请求 059 else { 060 request.appendParasToUrl(); 061 doProcessGetRequest(request, response); 062 } 063 064 } catch (Throwable ex) { 065 response.setError(ex); 066 } finally { 067 response.close(); 068 } 069 } 070 071 private void doProcessGetRequest(JbootHttpRequest request, JbootHttpResponse response) throws Exception { 072 Request okHttpRequest = new Request.Builder() 073 .url(request.getRequestUrl()) 074 .build(); 075 076 077 doProcessRequest(request, response, okHttpRequest); 078 } 079 080 private void doProcessPostRequest(final JbootHttpRequest request, JbootHttpResponse response) throws Exception { 081 RequestBody requestBody = null; 082 if (request.isMultipartFormData()) { 083 MultipartBody.Builder builder = new MultipartBody.Builder(); 084 for (Map.Entry<String, Object> entry : request.getParams().entrySet()) { 085 if (entry.getValue() instanceof File) { 086 File file = (File) entry.getValue(); 087 builder.addFormDataPart(entry.getKey(), file.getName(), RequestBody.create(MediaType.parse("application/octet-stream"), file)); 088 } else { 089 builder.addFormDataPart(entry.getKey(), entry.getValue() == null ? "" : entry.getValue().toString()); 090 } 091 } 092 requestBody = builder.build(); 093 } else { 094// FormBody.Builder builder = new FormBody.Builder(); 095// for (Map.Entry<String, Object> entry : request.getParams().entrySet()) { 096// builder.add(entry.getKey(), entry.getValue() == null ? "" : entry.getValue().toString()); 097// } 098// requestBody = builder.build(); 099 100 MediaType mediaType = MediaType.parse(request.getContentType()); 101 requestBody = RequestBody.create(mediaType, request.getUploadBodyString()); 102 } 103 104 105 Request okHttpRequest = new Request.Builder().url(request.getRequestUrl()) 106 .post(requestBody) 107 .build(); 108 109 110 doProcessRequest(request, response, okHttpRequest); 111 } 112 113 private void doProcessRequest(JbootHttpRequest request, JbootHttpResponse response, Request okHttpRequest) throws Exception { 114 OkHttpClient client = getClient(request); 115 Call call = client.newCall(okHttpRequest); 116 Response okHttpResponse = call.execute(); 117 response.setResponseCode(okHttpResponse.code()); 118 response.setContentType(okHttpResponse.body().contentType().type()); 119 120 if (request.isReadBody()) { 121 response.copyStream(okHttpResponse.body().byteStream()); 122 } 123 } 124 125 126 private OkHttpClient getClient(JbootHttpRequest request) throws Exception { 127 if (request.getRequestUrl().toLowerCase().startsWith("https")) { 128 return getHttpsClient(request); 129 } 130 131 132 OkHttpClient.Builder builder = new OkHttpClient.Builder(); 133 if (request.getProxy() != null) { 134 builder.proxy(request.getProxy()); 135 } 136 137 return builder.build(); 138 } 139 140 public OkHttpClient getHttpsClient(JbootHttpRequest request) throws Exception { 141 OkHttpClient.Builder builder = new OkHttpClient.Builder(); 142 //自定义 sslContext 143 if (request.getSslContext() != null) { 144 SSLSocketFactory ssf = request.getSslContext().getSocketFactory(); 145 builder.sslSocketFactory(ssf, trustAnyTrustManager); 146 } 147 //配置证书的路径和密码 148 else if (request.getCertPath() != null && request.getCertPass() != null) { 149 KeyStore clientStore = KeyStore.getInstance("PKCS12"); 150 clientStore.load(request.getCertInputStream(), request.getCertPass().toCharArray()); 151 152 KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); 153 keyManagerFactory.init(clientStore, request.getCertPass().toCharArray()); 154 KeyManager[] keyManagers = keyManagerFactory.getKeyManagers(); 155 156 157 TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 158 trustManagerFactory.init(clientStore); 159 160 TrustManager[] trustManagers = trustManagerFactory.getTrustManagers(); 161 162 163 SSLContext sslContext = SSLContext.getInstance("TLS"); 164 sslContext.init(keyManagers, trustManagers, new SecureRandom()); 165 166 X509TrustManager x509TrustManager = trustAnyTrustManager; 167 if (trustManagers != null && trustManagers.length > 0 && trustManagers[0] instanceof X509TrustManager) { 168 x509TrustManager = (X509TrustManager) trustManagers[0]; 169 } 170 171 builder.sslSocketFactory(sslContext.getSocketFactory(), x509TrustManager); 172 173 } else { 174 builder.hostnameVerifier(hnv); 175 SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE"); 176 if (sslContext != null) { 177 TrustManager[] trustManagers = {trustAnyTrustManager}; 178 sslContext.init(null, trustManagers, new SecureRandom()); 179 builder.sslSocketFactory(sslContext.getSocketFactory(), trustAnyTrustManager); 180 } 181 } 182 183 return builder.build(); 184 } 185 186 187 private static X509TrustManager trustAnyTrustManager = new X509TrustManager() { 188 @Override 189 public void checkClientTrusted(X509Certificate[] chain, String authType) { 190 } 191 192 @Override 193 public void checkServerTrusted(X509Certificate[] chain, String authType) { 194 } 195 196 @Override 197 public X509Certificate[] getAcceptedIssuers() { 198 return new X509Certificate[0]; 199 } 200 }; 201 202 private static HostnameVerifier hnv = (hostname, session) -> true; 203}