All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alibaba.csb.sdk.HttpCaller Maven / Gradle / Ivy

The newest version!
package com.alibaba.csb.sdk;

import com.alibaba.csb.sdk.internel.DiagnosticHelper;
import com.alibaba.csb.sdk.internel.HttpClientConnManager;
import com.alibaba.csb.sdk.internel.HttpClientHelper;
import com.alibaba.csb.sdk.security.SignUtil;
import com.alibaba.csb.sdk.security.SpasSigner;
import com.alibaba.csb.trace.TraceData;
import com.alibaba.csb.utils.IPUtils;
import com.alibaba.csb.utils.LogUtils;
import com.alibaba.csb.utils.TraceIdUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.protocol.HTTP;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;

import java.io.*;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

/**
 * SDK工具类,用来向服务端发送HTTP请求,请求支持POST/GET方式.
 * 如果提供了AccessKey和SecurityKey参数信息,它能够在内部将请求消息进行签名处理,然后由CSB服务端进行验证.
 *
 * 
 *
 * {@code
 * import com.alibaba.csb.sdk.HttpCaller;
 * import com.alibaba.csb.sdk.HttpCallerException;
 * ...
 *
 * (1) 直接调用方式 (已过期,不推荐)
 *
 * Map params = new HashMap();
 *
 * Object smd = ... // 一个具体的复杂对象
 * if (smd != null) {
 *   String data = JSON.toJSONString(smd); //转换为JSON String
 *   params.put("data", data);
 * }
 *
 * // -- Tip: 如果调用者无法获得复杂对象参数类,则可以使用全map的方式设置json串,举例,对于json串
 * // {"f1":{"f11":"v11", "f12":["v121","v122"]}, "f2":"wiseking"}
 * // 它是可以通过如下的方式进行转换而来
 * Map map = new HashMap();
 *
 * Map mapF1 = new HashMap();
 * mapF1.put("f11", "v11");
 * mapF1.put("f12", Arrays.asList("v121","v122"));
 * map.put("f1", mapF1);
 *
 * map.put("f2", "wiseking");
 * String jsonData = JSON.toJSONString(map);
 * // -- Tip End
 *
 * params.put("name", "abcd"); //普通的串对象
 * params.put("password", "abcd"); //普通的串对象
 *
 *
 * String requestURL = "http://gateway.abc.com:8086/CSB";
 * String API_NAME = "login_system";
 * String version = "1.0.0";
 * String ak = "xxxxxx";
 * String sk = "xxxxxx"; //用户安全校验的签名密钥对
 *
 * try {
 *   String result = HttpCaller.doPost(requestURL, API_NAME, version, params, ak, sk);
 *
 *   if (result != null) {
 *      //返回结果处理, 如转换为JSON对象
 *      ...
 *   }
 * } catch (HttpCallerException ie) {
 *      //print error
 * }}
 *
 * (2) 也可以使用第二种Builder的方式构造调用参数,然后进行调用 (推荐用法)
 * import com.alibaba.csb.sdk.HttpParameters;
 * import com.alibaba.csb.sdk.HttpCaller;
 * import com.alibaba.csb.sdk.HttpCallerException;
 *
 * HttpParameters.Builder builder = HttpParameters.newBuilder();
 *
 * builder.requestURL("http://broker-ip:8086/CSB?arg0=123") // 设置请求的URL
 *      .api("test") // 设置服务名
 *      .version("1.0.0") // 设置版本号
 *      .method("get") // 设置调用方式, get/post
 *      .accessKey("ak").secretKey("sk"); // 设置accessKey 和 设置secretKey
 *
 *  // 设置请求参数
 *  builder.putParamsMap("key1", "value1");
 *  builder.putParamsMap("key2", "{\"a\":value1}"); // json format value
 *
 *  //设置请求调用方式
 *  builder.method("get");
 *
 *  //设置透传的HTTP Headers
 *  builder.putHeaderParamsMap("header1", "value1");
 *  builder.putHeaderParamsMap("header2", "value2");
 *
 *  //进行调用 返回结果
 *  String result = null;
 *  try {
 *    result = HttpCaller.invoke(builder.build());
 *  } catch (HttpCallerException e) {
 *    // error process
 *  }
 *
 *  try {
 *      	// 重启设置请求参数
 *      	builder.clearParamsMap();
 *      	builder.putParamsMap("key1", "value1---new");
 *      	builder.putParamsMap("key2", "{\"a\":\"value1-new\"}");
 *
 *      	// 使用post方式调用
 *      	builder.method("post");
 *      	HttpCaller.invoke(builder.build());
 *  } catch (HttpCallerException e) {
 *      	// error process
 *  }
 *
 * (3) 如果使用json或者bytes内容的作为http body,使用下面的方法
 *
 *  //构造ContentBody对象
 *  ContentBody cb = new ContentBody(jsonObject.toSring());
 *  //或者
 *  cb = new ContentBody(file2bytes);
 *
 *     //ContentBody传递,要求使用post方式进行调用
 *     //如果需要传递请求参数 可以拼接到请求URL中,或者设置paramsMap参数由SDK内部进行拼接
 *     HttpParameters.Builder builder = HttpParameters.newBuilder();
 *     builder.requestURL("http://broker-ip:8086/CSB?arg0=123") // 设置请求的URL,可以拼接URL请求参数
 *      .api("test") // 设置服务名
 *      .version("1.0.0") // 设置版本号
 *      .method("post") // 设置调用方式, 必须为 post
 *      .accessKey("ak").secretKey("sk"); // 设置accessKey 和 设置secretKey
 *
 *     builder.contentBody(cb);
 *
 *      //进行调用,返回结果
 *      String result = null;
 *      try {
 *      	result = HttpCaller.invoke(builder.build());
 *      } catch (HttpCallerException e) {
 *      	// error process
 *      }
 *
 *
 * 高级功能
 * 1. 设置代理地址
 *    String proxyHost = "...";
 *    int proxyPort = ...;
 *    HttpCaller.setProxyHost(proxyHost, proxyPort, null); //注意:本次设置只对本线程起作用
 *    ...
 *    HttpCaller.doPost(), doGet() or invoke();
 *
 * 2. 关于连接参数的设置:
 *   a. 可以为http/https设置以下的全局性系统参数:
 *      -Dhttp.caller.connection.max          设置连接池的最大连接数,默认是200
 *      -Dhttp.caller.connection.timeout      设置连接超时时间(毫秒),默认是-1, 永不超时
 *      -Dhttp.caller.connection.so.timeout   设置读取超时时间(毫秒),默认是-1, 永不超时
 *      -Dhttp.caller.connection.cr.timeout   设置从连接池获取连接实例的超时(毫秒),默认是-1, 永不超时
 *      -Dhttp.caller.connection.async        设置使用nio,默认fasle:同步io,true:nio
 *      -Dhttp.caller.connection.keepalive.timeout    长连接超时时间(秒),默认75
 *      -Dhttp.caller.skip.connection.pool    如何设置为true,则不使用连接池。默认行为是false,使用连接池(支持长连接)
 *   b. 也可以使用下面的方法设置以上的某一个或者多个参数:
 *      Map sysParams = new HashMap();
 *      sysParams.put("http.caller.connection.timeout","3000"); //设置连接超时为3秒
 *      HttpCaller.setConnectionParams(sysParams); //注意:本次设置只对本线程起作用
 *      ...
 *      HttpCaller.doPost(), doGet() or invoke();
 * 3. 设置debug:
 *    -Dhttp.caller.DEBUG=true
 * 
* * @author Alibaba Middleware CSB Team * @author [email protected] * @since 2016 */ public class HttpCaller { protected static boolean warmupFlag = false; protected static final String RESTFUL_PATH_SIGNATURE_KEY = "csb_restful_path_signature_key"; protected static final String DEFAULT_RESTFUL_PROTOCOL_VERSION = "1.0"; protected static final String RESTFUL_PROTOCOL_VERION_KEY = "restful_protocol_version"; // TODO: must set truststore for ssl public static final String trustCA = System.getProperty("http.caller.ssl.trustca"); public static final String DEFAULT_CHARSET = HTTP.UTF_8; public static final String GZIP = "gzip"; protected static String defaultAK = null; protected static String defaultSK = null; protected static ThreadLocal toCurlCmd = new ThreadLocal(); protected static ThreadLocal toHttpRequest = new ThreadLocal(); protected static ThreadLocal proxyConfigThreadLocal = new ThreadLocal(); protected static final RequestConfig.Builder requestConfigBuilder = HttpClientConnManager.createConnBuilder(); protected static final ThreadLocal requestConfigBuilderLocal = new ThreadLocal(); protected static AtomicReference BIZ_ID_KEY = new AtomicReference(); public static final long TOTAL_FILE_SIZE; static { //默认15M TOTAL_FILE_SIZE = Integer.getInteger("csb_httpAttachmentTotalMBSize", 64) * 1024 * 1024; } protected HttpCaller() { } /** * init bizIdKey * * @param bizIdKey */ public static void bizIdKey(String bizIdKey) { BIZ_ID_KEY.compareAndSet(null, bizIdKey); } /** * get bizIdkey * * @return */ public static String bizIdKey() { String bizIdKey = BIZ_ID_KEY.get(); return bizIdKey == null ? CsbSDKConstants.BIZID_KEY : bizIdKey; } /** * 加载HttpSDK所需要的类 (如,签名相关的) *

* 注意:这是一个高时间代价的启动方法,建议在整个JVM范围内,在使用HttpCaller调用具体的服务前,调用且只调用一次 */ public static synchronized void warmup() { if (warmupFlag) { return; } SignUtil.warmup(); warmupFlag = true; } /** * 为接下来的调用设置代理参数。 注意:本次设置只对本线程起作用 * * @param hostname * @param port * @param scheme 如果设置为null时, scheme为 "http" */ public static void setProxyHost(final String hostname, final int port, final String scheme) { proxyConfigThreadLocal.set(new HttpHost(hostname, port, scheme)); } /** * 为接下来的调用设置新的连接参数。 注意:本次设置只对本线程起作用 * * @param params */ public static void setConnectionParams(Map params) { if (params == null || params.size() == 0) { requestConfigBuilderLocal.set(requestConfigBuilder); } else { requestConfigBuilderLocal.set(HttpClientConnManager.createConnBuilder(params)); } } private static RequestConfig getRequestConfig() { RequestConfig.Builder rcBuilder = null; if (requestConfigBuilderLocal.get() == null) { rcBuilder = requestConfigBuilder; } else { rcBuilder = requestConfigBuilderLocal.get(); } rcBuilder.setProxy(proxyConfigThreadLocal.get()); return rcBuilder.build(); } /** * 当参数flag设置为true时, 使当前调用doGet/doPost的线程不做真实的调用而是生成curl命令请求串返回 * * @param flag */ public static void setCurlResponse(boolean flag) { toCurlCmd.set(true); } private static boolean isCurlResponse() { return toCurlCmd.get() != null && toCurlCmd.get() == true; } public static void setToHttpRequest(boolean flag) { toHttpRequest.set(true); } /** * 一次设置,只能读取一次,避免上下文影响 */ private static boolean isToHttpRequest() { try { return toHttpRequest.get() != null && toHttpRequest.get() == true; } finally { toHttpRequest.remove(); } } /** * 设置默认的AK/SK, 以后发送请求可以使用该默认值进行签名, *

* 注意: 这个方法设置静态的accessKey,secretKey变量到HttpCaller中,所以会影响所有的使用HttpCaller的方法,即 * 如果调用方法不指定AK/SK, 会使用这里本方法设置的AK/SK. * * @param accessKey 访问key * @param secretKey 安全key */ public static void setCredential(String accessKey, String secretKey) { defaultAK = accessKey; defaultSK = secretKey; } /** * 把一个串的字符集从旧的的字符集到一个新的字符集合, 一个辅助方法,主要用于HTTP调用返回值的转换 * * @param result 要装换的字符串 * @param OldcharsetName 源编码方式 * @param charsetName 目标编码方式 * @return 返回转换后的字符串 * @throws HttpCallerException */ public static String changeCharset(String result, String OldcharsetName, String charsetName) throws HttpCallerException { if (result == null) { return result; } try { return new String(result.getBytes(OldcharsetName), charsetName); } catch (UnsupportedEncodingException e) { throw new HttpCallerException(e); } } /** * 把一个串的字符集从"ISO-8859-1"改变到"UTF-8", 一个辅助方法,主要用于HTTP调用返回值的转换 * * @param result 要装换的字符串 * @return 返回转换后的字符串 * @throws HttpCallerException */ public static String changeCharset(String result) throws HttpCallerException { return changeCharset(result, "ISO-8859-1", DEFAULT_CHARSET); } /** * 方法说明: 使用GET的方式发送请求服务,如果设置过默认AK/SK, 则使用它们将请求消息进行签名 * * @param requestURL 请求的服务URL, 如:http://abc.com:8086/CSB * @param apiName API名字(服务名) * @param paramsMap 请求参数key-value参数列表,注:可以将JSON对象转换为String作为参数值 * @return 调用的返回值,按约定进行解析 (如 JOSN串转换成对象) * @throws HttpCallerException 调用过程中发生的任何异常 * @deprecated 1. 新版本(1.0.2.1+)的CSB服务需要定义服务版本参数 * 2. 推荐使用invoke()方法,并使用HttpParameters构造相关的参数 */ public static String doGet(String requestURL, String apiName, Map paramsMap) throws HttpCallerException { return doGet(requestURL, apiName, paramsMap, defaultAK, defaultSK); } /** * 方法说明: 使用GET的方式发送请求服务,并使用指定的AK/SK将请求消息进行签名 * * @param requestURL 请求的服务URL, 如:http://abc.com:8080/test/abc * @param apiName API名字(服务名) * @param paramsMap 请求参数key-value参数列表,注:可以将JSON对象转换为String作为参数值 * @param accessKey 访问key * @param secretKey 安全keyx * @return 调用的返回值,按约定进行解析 (如 JOSN串转换成对象) * @throws HttpCallerException 调用过程中发生的任何异常 * @deprecated 推荐使用invoke()方法,并使用HttpParameters构造相关的参数 */ public static String doGet(String requestURL, String apiName, Map paramsMap, String accessKey, String secretKey) throws HttpCallerException { return doGet(requestURL, apiName, null, paramsMap, accessKey, secretKey); } /** * 使用GET的方式发送请求服务,并使用指定的AK/SK将请求消息进行签名 * * @param requestURL 请求的服务URL, 如:http://abc.com:8086/CSB, 如果URL里的请求参数有特殊字符(如 '&'),需要先将次值进行URL Encode处理 * @param apiName API名字(服务名) * @param version API版本号 * @param paramsMap 请求参数key-value参数列表,注:可以将JSON对象转换为String作为参数值,如果URL里的请求参数有特殊字符(如 '&'),需要先将次值进行URL Encode处理 * @param accessKey 访问key * @param secretKey 安全key * @return 调用的返回值,按约定进行解析 (如 JOSN串转换成对象) * @throws HttpCallerException 调用过程中发生的任何异常 * @deprecated 推荐使用invoke()方法,并使用HttpParameters构造相关的参数 */ public static String doGet(String requestURL, String apiName, String version, Map paramsMap, String accessKey, String secretKey) throws HttpCallerException { return doGet(requestURL, apiName, version, paramsMap, accessKey, secretKey, null, null); } /** * 使用GET的方式发送请求服务,并使用指定的AK/SK将请求消息进行签名 * * @param requestURL 请求的服务URL, 如:http://abc.com:8086/CSB, 如果URL里的请求参数有特殊字符(如 '&'),需要先将次值进行URL Encode处理 * @param apiName API名字(服务名) * @param version API版本号 * @param paramsMap 请求参数key-value参数列表,注:可以将JSON对象转换为String作为参数值,如果URL里的请求参数有特殊字符(如 '&'),需要先将次值进行URL Encode处理 * @param accessKey 访问key * @param secretKey 安全key * @param signImpl 签名算法实现类名 * @param verifySignImpl 验签算法实现类名 * @return 调用的返回值,按约定进行解析 (如 JOSN串转换成对象) * @throws HttpCallerException 调用过程中发生的任何异常 * @deprecated 推荐使用invoke()方法,并使用HttpParameters构造相关的参数 */ public static String doGet(String requestURL, String apiName, String version, Map paramsMap, String accessKey, String secretKey, String signImpl, String verifySignImpl) throws HttpCallerException { HttpParameters hp = HttpParameters.newBuilder().requestURL(requestURL).api(apiName).version(version).putParamsMapAll(paramsMap) .accessKey(accessKey).secretKey(secretKey).signImpl(signImpl).verifySignImpl(verifySignImpl) .build(); return doGet(hp, null).getResponseStr(); } /** * 获取签名串 * * @param requestURL 请求的服务URL, 如:http://abc.com:8086/CSB, 如果URL里的请求参数有特殊字符(如 '&'),需要先将次值进行URL Encode处理 * @param apiName API名字(服务名) * @param version API版本号 * @param paramsMap 请求参数key-value参数列表,注:可以将JSON对象转换为String作为参数值,如果URL里的请求参数有特殊字符(如 '&'),需要先将次值进行URL Encode处理 * @param accessKey 访问key * @param secretKey 安全key * @return 发送CSB请求需要增加的httpHeader,包含签名串等 */ public static Map getCsbHeaders(String requestURL, String apiName, String version, Map paramsMap, String accessKey, String secretKey) throws HttpCallerException { return getCsbHeaders(requestURL, apiName, version, paramsMap, accessKey, secretKey, null, null, null, SpasSigner.SigningAlgorithm.HmacSHA1.name()); } /** * 获取签名串 * * @param requestURL 请求的服务URL, 如:http://abc.com:8086/CSB, 如果URL里的请求参数有特殊字符(如 '&'),需要先将次值进行URL Encode处理 * @param apiName API名字(服务名) * @param version API版本号 * @param paramsMap 请求参数key-value参数列表,注:可以将JSON对象转换为String作为参数值,如果URL里的请求参数有特殊字符(如 '&'),需要先将次值进行URL Encode处理 * @param accessKey 访问key * @param secretKey 安全key * @return 发送CSB请求需要增加的httpHeader,包含签名串等 */ public static Map getCsbHeaders(String requestURL, String apiName, String version, Map paramsMap, String accessKey, String secretKey, String charset) throws HttpCallerException { return getCsbHeaders(requestURL, apiName, version, paramsMap, accessKey, secretKey, null, null, charset, SpasSigner.SigningAlgorithm.HmacSHA1.name()); } /** * 获取签名串 * * @param requestURL 请求的服务URL, 如:http://abc.com:8086/CSB, 如果URL里的请求参数有特殊字符(如 '&'),需要先将次值进行URL Encode处理 * @param apiName API名字(服务名) * @param version API版本号 * @param paramsMap 请求参数key-value参数列表,注:可以将JSON对象转换为String作为参数值,如果URL里的请求参数有特殊字符(如 '&'),需要先将次值进行URL Encode处理 * @param accessKey 访问key * @param secretKey 安全key * @param signImpl 签名算法实现类名 * @param verifySignImpl 验签算法实现类名 * @param charset 字符集 * @param signAlgothrim 签名算法 * @return 发送CSB请求需要增加的httpHeader,包含签名串等 */ public static Map getCsbHeaders(String requestURL, String apiName, String version, Map paramsMap , String accessKey, String secretKey, String signImpl, String verifySignImpl , String charset, String signAlgothrim) throws HttpCallerException { Map> urlParamsMap = HttpClientHelper.parseUrlParamsMap(requestURL, charset, true); HttpClientHelper.mergeParams(urlParamsMap, paramsMap); return HttpClientHelper.newParamsMap(urlParamsMap, apiName, version, accessKey, secretKey, true, false, null, null, signImpl, verifySignImpl, signAlgothrim); } private static HttpReturn doGet(HttpParameters hp, Map extSignHeadersMap) throws HttpCallerException { if (!hp.getHeaderParamsMap().containsKey(CsbSDKConstants.TRACEID_KEY)) { hp.getHeaderParamsMap().put(TraceData.TRACEID_KEY, TraceIdUtils.generate()); hp.getHeaderParamsMap().put(TraceData.RPCID_KEY, TraceData.RPCID_DEFAULT); } final String requestURL = hp.getRequestUrl(); String apiName = hp.getApi(); String version = hp.getVersion(); Map> paramsMap = hp.getParamsMap(); String accessKey = hp.getAccessKey(); String secretKey = hp.getSecretkey(); String signAlgothrim = hp.getSignAlgorithm(); Map directParamsMap = hp.getHeaderParamsMap(); String restfulProtocolVersion = hp.getRestfulProtocolVersion(); HttpReturn ret = new HttpReturn(); ret.diagnosticFlag = hp.isDiagnostic(); long startT = System.currentTimeMillis(); long initT = startT; DiagnosticHelper.setStartTime(ret, initT); HttpClientHelper.validateParams(apiName, accessKey, secretKey, paramsMap); String charset = hp.getContentType() == null || hp.getContentType().getCharset() == null ? null : hp.getContentType().getCharset().name(); Map> urlParamsMap = HttpClientHelper.parseUrlParamsMap(requestURL, charset, true); HttpClientHelper.mergeParamsList(urlParamsMap, paramsMap); if (SdkLogger.isLoggable()) { SdkLogger.print("--+++ prepare params costs = " + (System.currentTimeMillis() - startT) + " ms "); } startProcessRestful(requestURL, restfulProtocolVersion, urlParamsMap); StringBuilder signDiagnosticInfo = DiagnosticHelper.getSignDiagnosticInfo(ret); Map headerParamsMap = HttpClientHelper.newParamsMap(urlParamsMap, apiName, version, accessKey, secretKey, hp.isTimestamp() , hp.isNonce(), extSignHeadersMap, signDiagnosticInfo, hp.getSignImpl(), hp.getVerifySignImpl(), signAlgothrim); if (hp.getContentType() != null) { headerParamsMap.put("Content-Type", hp.getContentType().toString()); } DiagnosticHelper.setSignDiagnosticInfo(ret, signDiagnosticInfo); endProcessRestful(restfulProtocolVersion, urlParamsMap, headerParamsMap); String newRequestURL = HttpClientHelper.generateAsEncodeRequestUrl(requestURL, charset, urlParamsMap); if (isCurlResponse()) { StringBuffer curl = new StringBuffer("curl "); curl.append(HttpClientHelper.genCurlHeaders(directParamsMap)); curl.append(HttpClientHelper.genCurlHeaders(headerParamsMap)); curl.append(" -k "); curl.append("\"").append(newRequestURL).append("\""); ret.response = curl.toString(); return ret; } if (isToHttpRequest()) { //根据请求消息,生成http请求内容。目前使用在控制台发送测试服务消息,通过命令通道转发 return new HttpReturn(newRequestURL, directParamsMap, headerParamsMap); } DiagnosticHelper.calcRequestSize(ret, newRequestURL, null, null); HttpGet httpGet = new HttpGet(newRequestURL); httpGet.setConfig(getRequestConfig()); // first step to set the direct http headers if (directParamsMap != null) HttpClientHelper.setHeaders(httpGet, directParamsMap); // normal headers have the chance to overwrite the direct headers. HttpClientHelper.setHeaders(httpGet, headerParamsMap); DiagnosticHelper.setRequestHeaders(ret, httpGet.getAllHeaders()); String msg = null; try { ret = doHttpReq(requestURL, httpGet, ret); DiagnosticHelper.setEndTime(ret, System.currentTimeMillis()); DiagnosticHelper.setInvokeTime(ret, System.currentTimeMillis() - initT); return ret; } catch (HttpCallerException e) { msg = e.getMessage(); throw e; } finally { log(hp, startT, requestURL, ret, msg); if (SdkLogger.isLoggable()) { SdkLogger.print("-- total = " + (System.currentTimeMillis() - initT) + " ms "); } } } private static void endProcessRestful(String restfulProtocolVersion, Map> urlParamsMap, Map headerParamsMap) { if (DEFAULT_RESTFUL_PROTOCOL_VERSION.equals(restfulProtocolVersion)) { urlParamsMap.remove(RESTFUL_PATH_SIGNATURE_KEY); headerParamsMap.put(RESTFUL_PROTOCOL_VERION_KEY, DEFAULT_RESTFUL_PROTOCOL_VERSION); } } private static void startProcessRestful(String requestURL, String restfulProtocolVersion, Map> urlParamsMap) throws HttpCallerException { if (DEFAULT_RESTFUL_PROTOCOL_VERSION.equals(restfulProtocolVersion)) { String path = HttpClientHelper.getUrlPathInfo(requestURL); if (path == null) { throw new HttpCallerException("this request is restful but the request path is null !"); } List values = new ArrayList(); values.add(path); urlParamsMap.put(RESTFUL_PATH_SIGNATURE_KEY, values); } } private static boolean isSSLProtocol(String requestUrl) { if (requestUrl == null) return false; if (requestUrl.trim().toLowerCase().startsWith("https://")) { return true; } return false; } private static CloseableHttpClient createSyncHttpClient(String requestURL) throws HttpCallerException { CloseableHttpClient httpClient = null; if (isSSLProtocol(requestURL)) { try { httpClient = HttpClients.custom().setSslcontext(new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() { public boolean isTrusted(java.security.cert.X509Certificate[] chain, String authType) throws java.security.cert.CertificateException { return true; } }).build()).setSSLHostnameVerifier(new org.apache.http.conn.ssl.NoopHostnameVerifier()).build(); } catch (KeyManagementException e) { throw new HttpCallerException(e); } catch (NoSuchAlgorithmException e) { throw new HttpCallerException(e); } catch (KeyStoreException e) { throw new HttpCallerException(e); } } else { httpClient = HttpClients.createDefault(); } return httpClient; } private static CloseableHttpAsyncClient createAsyncHttpClient(String requestURL) throws HttpCallerException { CloseableHttpAsyncClient httpClient = null; if (isSSLProtocol(requestURL)) { try { httpClient = HttpAsyncClients.custom().setSSLHostnameVerifier(new org.apache.http.conn.ssl.NoopHostnameVerifier()).setSSLContext(new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() { public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { return true; } }).build()).build(); } catch (KeyManagementException e) { throw new HttpCallerException(e); } catch (NoSuchAlgorithmException e) { throw new HttpCallerException(e); } catch (KeyStoreException e) { throw new HttpCallerException(e); } } else { httpClient = HttpAsyncClients.createDefault(); } httpClient.start(); return httpClient; } /** * 以GET的方式发送URL请求 * * @param requestURL 请求的服务URL, 如:"http://abc.com:8086/CSB?name=test&value=123" * @return 返回的JSON串 * @throws HttpCallerException */ public static String doGet(String requestURL) throws HttpCallerException { HttpGet httpGet = new HttpGet(requestURL); httpGet.setConfig(getRequestConfig()); HttpClientHelper.printDebugInfo("requestURL=" + requestURL); return doHttpReq(requestURL, httpGet, null).getResponseStr(); } /** * 使用POST方式调用HTTP服务 * * @param requestURL 请求的服务URL, 如:http://abc.com:8086/CSB/abc, 如果URL里的请求参数有特殊字符(如 '&'),需要先将次值进行URL Encode处理 * @param apiName API名字(服务名) * @param paramsMap 请求参数key-value参数列表,注:可以将JSON对象转换为String作为参数值 * @return 调用的返回值,按约定进行解析 (如 JOSN串转换成对象) * @throws HttpCallerException 调用过程中发生的任何异常 * @deprecated 1. 新版本的CSB服务需要定义服务版本参数 * 2. 推荐使用invoke()方法,并使用HttpParameters构造相关的参数 */ public static String doPost(String requestURL, String apiName, Map paramsMap) throws HttpCallerException { return doPost(requestURL, apiName, null, paramsMap); } /** * 使用POST方式调用HTTP服务 * * @param requestURL: 请求的服务URL, 如:http://abc.com:8086/CSB/abc, 如果URL里的请求参数有特殊字符(如 '&'),需要先将次值进行URL Encode处理 * @param apiName: API名字(服务名) * @param version: API版本号 * @param paramsMap: 请求参数key-value参数列表,注:可以将JSON对象转换为String作为参数值 * @return 调用的返回值,按约定进行解析 (如 JOSN串转换成对象) * @throws HttpCallerException 调用过程中发生的任何异常 * @deprecated 推荐使用invoke()方法,并使用HttpParameters构造相关的参数 */ public static String doPost(String requestURL, String apiName, String version, Map paramsMap) throws HttpCallerException { return doPost(requestURL, apiName, version, paramsMap, defaultAK, defaultSK); } /** * 使用POST方式调用HTTP服务 * * @param requestURL 请求的服务URL, 如:http://abc.com:8086/CSB/abc, 如果URL里的请求参数有特殊字符(如 '&'),需要先将次值进行URL Encode处理 * @param apiName API名字(服务名) * @param paramsMap 请求参数key-value参数列表,注:可以将JSON对象转换为String作为参数值 * @param accessKey 访问key * @param secretKey 安全key * @return 调用的返回值,按约定进行解析 (如 JOSN串转换成对象) * @throws HttpCallerException 调用过程中发生的任何异常 * @deprecated 推荐使用invoke()方法,并使用HttpParameters构造相关的参数 */ public static String doPost(String requestURL, String apiName, Map paramsMap, String accessKey, String secretKey) throws HttpCallerException { return doPost(requestURL, apiName, paramsMap, accessKey, secretKey, null, null); } /** * 使用POST方式调用HTTP服务 * * @param requestURL 请求的服务URL, 如:http://abc.com:8086/CSB/abc, 如果URL里的请求参数有特殊字符(如 '&'),需要先将次值进行URL Encode处理 * @param apiName API名字(服务名) * @param paramsMap 请求参数key-value参数列表,注:可以将JSON对象转换为String作为参数值 * @param accessKey 访问key * @param secretKey 安全key * @param signImpl 签名算法实现类名 * @param verifySignImpl 验签算法实现类名 * @return 调用的返回值,按约定进行解析 (如 JOSN串转换成对象) * @throws HttpCallerException 调用过程中发生的任何异常 * @deprecated 推荐使用invoke()方法,并使用HttpParameters构造相关的参数 */ public static String doPost(String requestURL, String apiName, Map paramsMap, String accessKey, String secretKey, String signImpl, String verifySignImpl) throws HttpCallerException { return doPost(requestURL, apiName, null, paramsMap, accessKey, secretKey, signImpl, verifySignImpl); } /** * 使用POST方式调用HTTP服务, 可以同时支持NameValuePair请求参数(拼接到请求URL中),并且传递contentBody * * @param requestURL 请求的服务URL, 如:http://abc.com:8086/CSB/abc, 如果URL里的请求参数有特殊字符(如 '&'),需要先将次值进行URL Encode处理 * @param apiName API名字(服务名) * @param version API版本号 * @param cb 直接设置contentBody, 内容可以是json串 或者 byte[] * @param accessKey 访问key * @param secretKey 安全key * @return 调用的返回值,按约定进行解析 (如 JOSN串转换成对象) * @throws HttpCallerException 调用过程中发生的任何异常 * @deprecated 推荐使用invoke()方法,并使用HttpParameters构造相关的参数 */ public static String doPost(String requestURL, String apiName, String version, ContentBody cb, String accessKey, String secretKey) throws HttpCallerException { return doPost(requestURL, apiName, version, cb, accessKey, secretKey, null, null); } /** * 使用POST方式调用HTTP服务, 可以同时支持NameValuePair请求参数(拼接到请求URL中),并且传递contentBody * * @param requestURL 请求的服务URL, 如:http://abc.com:8086/CSB/abc, 如果URL里的请求参数有特殊字符(如 '&'),需要先将次值进行URL Encode处理 * @param apiName API名字(服务名) * @param version API版本号 * @param cb 直接设置contentBody, 内容可以是json串 或者 byte[] * @param accessKey 访问key * @param secretKey 安全key * @param signImpl 签名算法实现类名 * @param verifySignImpl 验签算法实现类名 * @return 调用的返回值,按约定进行解析 (如 JOSN串转换成对象) * @throws HttpCallerException 调用过程中发生的任何异常 * @deprecated 推荐使用invoke()方法,并使用HttpParameters构造相关的参数 */ public static String doPost(String requestURL, String apiName, String version, ContentBody cb, String accessKey, String secretKey, String signImpl, String verifySignImpl) throws HttpCallerException { HttpParameters hp = HttpParameters.newBuilder().requestURL(requestURL).api(apiName).version(version) .contentBody(cb).accessKey(accessKey).secretKey(secretKey).signImpl(signImpl).verifySignImpl(verifySignImpl) .build(); return doPost(hp, null).getResponseStr(); } /** * 所有doPost的真正入口参数,httppost逻辑集成在这个方法中 * resHttpHeaders 是否返回http reponse headers, 如果请求参数不为空,会出现 {"_HTTP_HEADERS":[{"key":"value"}]}返回部分 * * @return * @throws HttpCallerException */ private static HttpReturn doPost(HttpParameters hp, Map extSignHeadersMap) throws HttpCallerException { if (!hp.getHeaderParamsMap().containsKey(CsbSDKConstants.TRACEID_KEY)) { hp.getHeaderParamsMap().put(TraceData.TRACEID_KEY, TraceIdUtils.generate()); hp.getHeaderParamsMap().put(TraceData.RPCID_KEY, TraceData.RPCID_DEFAULT); } final String requestURL = hp.getRequestUrl(); String apiName = hp.getApi(); String version = hp.getVersion(); Map> paramsMap = hp.getParamsMap(); ContentBody cb = hp.getContentBody(); String accessKey = hp.getAccessKey(); String secretKey = hp.getSecretkey(); String signAlgothrim = hp.getSignAlgorithm(); Map directHeaderParamsMap = hp.getHeaderParamsMap(); String restfulProtocolVersion = hp.getRestfulProtocolVersion(); boolean nonceFlag = hp.isNonce(); HttpReturn ret = new HttpReturn(); ret.diagnosticFlag = hp.isDiagnostic(); long startT = System.currentTimeMillis(); DiagnosticHelper.setStartTime(ret, startT); HttpClientHelper.validateParams(apiName, accessKey, secretKey, paramsMap); String charset = hp.getContentType() == null || hp.getContentType().getCharset() == null ? null : hp.getContentType().getCharset().name(); Map> urlParamsMap = HttpClientHelper.parseUrlParamsMap(requestURL, charset, true); String newRequestURL = HttpClientHelper.generateAsEncodeRequestUrl(requestURL, charset, urlParamsMap); HttpClientHelper.mergeParamsList(urlParamsMap, paramsMap); startProcessRestful(newRequestURL, restfulProtocolVersion, urlParamsMap); if (cb != null && hp.isSignContentBody()) { //判断body是否参与签名 // urlParamsMap.put(ContentBody.CONTENT_BODY_SIGN_KEY, Arrays.asList(cb.getBytesContentBody())); } StringBuilder signDiagnosticInfo = DiagnosticHelper.getSignDiagnosticInfo(ret); Map headerParamsMap = HttpClientHelper.newParamsMap(urlParamsMap, apiName, version, accessKey, secretKey, true, nonceFlag, extSignHeadersMap, signDiagnosticInfo, hp.getSignImpl(), hp.getVerifySignImpl(), signAlgothrim); DiagnosticHelper.setSignDiagnosticInfo(ret, signDiagnosticInfo); endProcessRestful(restfulProtocolVersion, urlParamsMap, headerParamsMap); if (isCurlResponse()) { return new HttpReturn(HttpClientHelper.createPostCurlString(newRequestURL, paramsMap, headerParamsMap, cb, directHeaderParamsMap)); } if (isToHttpRequest()) { //根据请求消息,生成http请求内容。目前使用在控制台发送测试服务消息,通过命令通道转发 String body; if (cb == null || cb.getStrContentBody() == null) { body = HttpClientHelper.getParamsUrlEncodingStr(paramsMap); } else { body = cb.getStrContentBody(); } return new HttpReturn(newRequestURL, directHeaderParamsMap, headerParamsMap, body); } DiagnosticHelper.calcRequestSize(ret, newRequestURL, paramsMap, cb); HttpPost httpPost = HttpClientHelper.createPost(newRequestURL, paramsMap, headerParamsMap, cb, hp.getAttachFileMap(), hp.getContentEncoding(), hp.getContentType()); DiagnosticHelper.setRequestHeaders(ret, httpPost.getAllHeaders()); HttpClientHelper.setDirectHeaders(httpPost, directHeaderParamsMap); httpPost.setConfig(getRequestConfig()); if (SdkLogger.isLoggable()) { SdkLogger.print("-- prepare time = " + (System.currentTimeMillis() - startT) + " ms "); } String msg = null; try { ret = doHttpReq(newRequestURL, httpPost, ret); DiagnosticHelper.setEndTime(ret, System.currentTimeMillis()); DiagnosticHelper.setInvokeTime(ret, System.currentTimeMillis() - startT); return ret; } catch (HttpCallerException e) { msg = e.getMessage(); throw e; } finally { log(hp, startT, requestURL, ret, msg); if (SdkLogger.isLoggable()) { SdkLogger.print("-- total = " + (System.currentTimeMillis() - startT) + " ms "); } } } private static HttpReturn doHttpReq(String requestURL, HttpRequestBase httpRequestBase, final HttpReturn ret) throws HttpCallerException { boolean async = isAsync(); if (async) { return doAsyncHttpReq(requestURL, httpRequestBase, ret); } else { return doSyncHttpReq(requestURL, httpRequestBase, ret); } } private static HttpReturn doSyncHttpReq(String requestURL, HttpRequestBase httpRequestBase, final HttpReturn ret) throws HttpCallerException { if (SdkLogger.isLoggable()) { SdkLogger.print("doSyncHttpReq "); } HttpReturn rret = ret; if (ret == null) { rret = new HttpReturn(); } long startT = System.currentTimeMillis(); CloseableHttpResponse response = null; CloseableHttpClient httpClient = null; if (HttpClientConnManager.HTTP_CLIENT != null) { httpClient = HttpClientConnManager.HTTP_CLIENT; } else { httpClient = createSyncHttpClient(requestURL); } if (SdkLogger.isLoggable()) { SdkLogger.print("--+++ get httpclient costs = " + (System.currentTimeMillis() - startT) + " ms "); startT = System.currentTimeMillis(); } try { try { response = httpClient.execute(httpRequestBase); rret.httpCode = response.getStatusLine().getStatusCode(); rret.responseHttpStatus = response.getStatusLine().toString(); rret.responseHeaders = HttpClientHelper.fetchResHeaders(response); rret.respHttpHeaderMap = HttpClientHelper.fetchResHeaderMap(response); fetchResponseBody(response, rret); return rret; } finally { if (response != null) { response.close(); } //don't close the client for reusing if (HttpClientConnManager.HTTP_CLIENT == null) { httpClient.close(); } if (SdkLogger.isLoggable()) { SdkLogger.print("-- http req & resp time = " + (System.currentTimeMillis() - startT) + " ms "); } } } catch (Exception e) { throw new HttpCallerException(e); } } private static HttpReturn doAsyncHttpReq(String requestURL, HttpRequestBase httpRequestBase, final HttpReturn ret) throws HttpCallerException { if (SdkLogger.isLoggable()) { SdkLogger.print("doAsyncHttpReq "); } HttpReturn rret = ret; if (ret == null) { rret = new HttpReturn(); } long startT = System.currentTimeMillis(); HttpResponse response = null; CloseableHttpAsyncClient httpClient = createAsyncHttpClient(requestURL); if (SdkLogger.isLoggable()) { SdkLogger.print("--+++ get httpclient costs = " + (System.currentTimeMillis() - startT) + " ms "); startT = System.currentTimeMillis(); } try { try { httpClient.start(); Future asyncFuture = httpClient.execute(httpRequestBase, null); long waitTime = getFutureGetTimeOut(); if (SdkLogger.isLoggable()) { SdkLogger.print("future waitTime :" + waitTime); } if (waitTime > 0) { response = asyncFuture.get(waitTime, TimeUnit.MILLISECONDS); } else { response = asyncFuture.get(); } rret.httpCode = response.getStatusLine().getStatusCode(); rret.responseHttpStatus = response.getStatusLine().toString(); rret.responseHeaders = HttpClientHelper.fetchResHeaders(response); rret.respHttpHeaderMap = HttpClientHelper.fetchResHeaderMap(response); fetchResponseBody(response, rret); return rret; } finally { httpClient.close(); if (SdkLogger.isLoggable()) { SdkLogger.print("-- http req & resp time = " + (System.currentTimeMillis() - startT) + " ms "); } } } catch (Exception e) { throw new HttpCallerException(e); } } static private void fetchResponseBody(HttpResponse response, HttpReturn rret) throws IOException { HttpEntity responseEntity = response.getEntity(); Header header = responseEntity.getContentType(); if (header == null) { rret.responseBytes = EntityUtils.toByteArray(responseEntity); rret.response = new String(rret.responseBytes, HTTP.UTF_8);//兼容csb历史版本的不规范 return; } String contentType = header.getValue(); if (contentType == null || contentType.equals("")) { rret.responseBytes = EntityUtils.toByteArray(responseEntity); rret.response = new String(rret.responseBytes, HTTP.UTF_8);//兼容csb历史版本的不规范 return; } contentType = contentType.toLowerCase(); if (contentType.startsWith("text") || contentType.contains("json") || contentType.contains("xml")) { rret.response = EntityUtils.toString(responseEntity); } else { rret.responseBytes = EntityUtils.toByteArray(responseEntity); } } /** * 使用POST方式调用HTTP服务 * * @param requestURL 请求的服务URL, 如:http://abc.com:8086/CSB * @param apiName API名字(服务名) * @param version API版本号 * @param paramsMap 请求参数key-value参数列表,注:可以将JSON对象转换为String作为参数值 * @param accessKey 访问key * @param secretKey 安全key * @return 调用的返回值,按约定进行解析 (如 JOSN串转换成对象) * @throws HttpCallerException 调用过程中发生的任何异常 * @deprecated 推荐使用invoke()方法,并使用HttpParameters构造相关的参数 */ public static String doPost(String requestURL, String apiName, String version, Map paramsMap, String accessKey, String secretKey) throws HttpCallerException { return doPost(requestURL, apiName, version, paramsMap, accessKey, secretKey, null, null); } /** * 使用POST方式调用HTTP服务 * * @param requestURL 请求的服务URL, 如:http://abc.com:8086/CSB * @param apiName API名字(服务名) * @param version API版本号 * @param paramsMap 请求参数key-value参数列表,注:可以将JSON对象转换为String作为参数值 * @param accessKey 访问key * @param secretKey 安全key * @param signImpl 签名算法实现类名 * @param verifySignImpl 验签算法实现类名 * @return 调用的返回值,按约定进行解析 (如 JOSN串转换成对象) * @throws HttpCallerException 调用过程中发生的任何异常 * @deprecated 推荐使用invoke()方法,并使用HttpParameters构造相关的参数 */ public static String doPost(String requestURL, String apiName, String version, Map paramsMap, String accessKey, String secretKey, String signImpl, String verifySignImpl) throws HttpCallerException { HttpParameters hp = HttpParameters.newBuilder().requestURL(requestURL).api(apiName).version(version).putParamsMapAll(paramsMap) .accessKey(accessKey).secretKey(secretKey).signImpl(signImpl).verifySignImpl(verifySignImpl) .build(); return doPost(hp, null).getResponseStr(); } /** * @param respHttpHeaderMap 当不为空时,会把所有http响应头放入此map */ public static String invoke(HttpParameters hp, Map respHttpHeaderMap) throws HttpCallerException { HttpReturn res = invokeReturn(hp); if (respHttpHeaderMap != null) { respHttpHeaderMap.putAll(res.respHttpHeaderMap); } return res.getResponseStr(); } /** * 使用invoke的方式进行http-api调用 * * @param hp 各种请求参数的集合类 * @param resHttpHeaders 当该传入参数不为空时,获取http response headers, {"key1":"value1","key2":"value2",...} * @return * @throws HttpCallerException */ public static String invoke(HttpParameters hp, StringBuffer resHttpHeaders) throws HttpCallerException { HttpReturn res = invokeReturn(hp); if (resHttpHeaders != null && res.responseHeaders != null) { resHttpHeaders.setLength(0); resHttpHeaders.append(res.responseHeaders); } return res.getResponseStr(); } /** * 新方法,支持复杂的返回对象(包括诊断信息) * * @param hp * @return * @throws HttpCallerException */ public static HttpReturn invokeReturn(HttpParameters hp) throws HttpCallerException { if (hp == null) throw new IllegalArgumentException("null parameter!"); HttpClientHelper.printDebugInfo("-- httpParameters=" + hp.toString()); hp.validate(); Map extSignHeaders = new HashMap(); if ("POST".equalsIgnoreCase(hp.getMethod()) || "CPOST".equalsIgnoreCase(hp.getMethod())) { return doPost(hp, extSignHeaders); } else return doGet(hp, extSignHeaders); } /** * 使用invoke的方式进行http-api调用 * * @param hp 各种请求参数的集合类 * @return * @throws HttpCallerException */ public static String invoke(HttpParameters hp) throws HttpCallerException { return invoke(hp, (StringBuffer) null); } /** * 一个便利方法,读取一个文件并把其内容转换为 byte[] * * @param file 文件的全路径, 最大支持的上传文件的尺寸为10M * @return * @throws HttpCallerException */ //TODO: remove this unrelated method out of the class public static byte[] readFileAsByteArray(String file) throws HttpCallerException { return readFile(new File(file)); } public static byte[] readFile(File file) { if (file.exists() && file.isFile() && file.canRead()) { try { return readInputStream(new FileInputStream(file)); } catch (IOException e) { throw new RuntimeException(e); } } else { throw new IllegalArgumentException("bad file to read:" + file); } } public static byte[] readInputStream(InputStream inputStream) { if (inputStream != null) { ByteArrayOutputStream bos = null; try { bos = new ByteArrayOutputStream(); byte[] b = new byte[1024]; int n; while ((n = inputStream.read(b)) != -1) { bos.write(b, 0, n); } return bos.toByteArray(); } catch (IOException e) { throw new RuntimeException(e); } finally { try { if (inputStream != null) inputStream.close(); if (bos != null) bos.close(); } catch (IOException e) { e.printStackTrace(); } } } else { throw new IllegalArgumentException("inputSteam must no null"); } } /** * 把二进制数据恢复成文件 * * @param body * @param filePath * @param fileName * @throws HttpCallerException */ //TODO: remove this unrelated method out of the class public static void recoveryFileFromBytes(byte[] body, String filePath, String fileName) throws HttpCallerException { try { String fileFullPath = filePath; if (fileFullPath.endsWith("/")) { fileFullPath += fileName; } else { fileFullPath = fileFullPath + "/" + fileName; } File f = new File(fileFullPath); FileOutputStream out = new FileOutputStream(f); try { out.write(body, 0, body.length); out.flush(); } finally { if (out != null) out.close(); } } catch (Exception e) { throw new HttpCallerException(e); } } /** * 判断是否使用NIO,由系统变量http.caller.connection.async设置,默认不用 * * @return */ public static boolean isAsync() { boolean async = false; String asyncConf = System.getProperty("http.caller.connection.async"); if (asyncConf != null && asyncConf.length() > 0) { async = Boolean.valueOf(asyncConf); } return async; } /** * 设置nio等待结果的时间,默认为3个等待时间总和外加0.1倍时间,0永不超时 * * @return */ public static long getFutureGetTimeOut() { RequestConfig requestConfig = getRequestConfig(); long waitTime = 0; int socketTimeOUt = requestConfig.getSocketTimeout(); if (socketTimeOUt > 0) { waitTime = waitTime + socketTimeOUt; } int crTimeOut = requestConfig.getConnectionRequestTimeout(); if (crTimeOut > 0) { waitTime = waitTime + crTimeOut; } int connTimeOut = requestConfig.getConnectTimeout(); if (connTimeOut > 0) { waitTime = waitTime + connTimeOut; } return (long) (waitTime * 1.1); } private static void log(HttpParameters hp, long startTime, String requestUrl, HttpReturn httpReturn, String msg) { long endTime = System.currentTimeMillis(); Map headers = hp.getHeaderParamsMap(); try { int qidx = requestUrl.indexOf("?"); String url = qidx > -1 ? requestUrl.substring(0, qidx) : requestUrl; int cidx = url.indexOf(":"); int pidx = url.indexOf(":", cidx + 3); if (pidx < 0) { pidx = url.indexOf("/", cidx + 3); } String dest = url.substring(cidx + 3, pidx); LogUtils.info("{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|{}", new Object[]{startTime, endTime, endTime - startTime , "HTTP", IPUtils.getLocalHostIP(), dest , headers.get(HttpCaller.bizIdKey()), headers.get(CsbSDKConstants.REQUESTID_KEY) , headers.get(CsbSDKConstants.TRACEID_KEY), headers.get(CsbSDKConstants.RPCID_KEY) , hp.getApi(), hp.getVersion() , defaultValue(hp.getAccessKey()), hp.getMethod() , url, httpReturn.httpCode, httpReturn.responseHttpStatus, defaultValue(msg)}); } catch (Throwable e) { LogUtils.exception(MessageFormat.format("csb invoke error, api:{0}, version:{1}", hp.getApi(), hp.getVersion()), e); } } private static String defaultValue(String val) { return val == null ? "" : val.trim(); } public static void main(String[] args) { String s = "http://100.100.80.76/api/admin/ServiceRepositoryAPI"; log(HttpParameters.newBuilder().build(), System.currentTimeMillis(), s, null, "ss"); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy