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

com.alibaba.csb.sdk.internel.HttpClientHelper Maven / Gradle / Ivy

package com.alibaba.csb.sdk.internel;

import com.alibaba.csb.sdk.*;
import com.alibaba.csb.sdk.security.SignUtil;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.GzipCompressingEntity;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.FormBodyPartBuilder;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.ByteArrayBody;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.InvalidParameterException;
import java.util.*;
import java.util.Map.Entry;

import static com.alibaba.csb.sdk.HttpCaller.GZIP;
//import com.alibaba.fastjson.JSONObject;

/**
 * HttpClient Helper Class
 */
public class HttpClientHelper {
    public static void printDebugInfo(String msg) {
        if (SdkLogger.isLoggable())
            SdkLogger.print(msg);
    }

    public static Map> convertStrMap2ListStrMap(Map paramsMap) {
        if (paramsMap == null) {
            return null;
        }
        Map> stringListMap = new HashMap>((int) (paramsMap.size() * 1.5));
        for (Entry entry : paramsMap.entrySet()) {
            stringListMap.put(entry.getKey(), Arrays.asList(entry.getValue()));
        }
        return stringListMap;
    }

    public static void mergeParams(Map> urlParamsMap, Map paramsMap) throws HttpCallerException {
        mergeParamsList(urlParamsMap, convertStrMap2ListStrMap(paramsMap));
    }

    public static void mergeParamsList(Map> urlParamsMap, Map> paramsMap) throws HttpCallerException {
        if (paramsMap != null) {
            for (Entry> kv : paramsMap.entrySet()) {
                urlParamsMap.put(kv.getKey(), kv.getValue());
            }
        }
    }

    /**
     * 根据输入的参数,关键值和扩展签名头列表 生成签名并返回最终的签名头列表
     *
     * @param paramsMap
     * @param apiName
     * @param version
     * @param accessKey
     * @param securityKey
     * @param extSignHeaders 放在extSignHeaders里的kv都参与签名
     * @return
     */
    public static Map newParamsMap(Map> paramsMap, String apiName, String version,
                                                   String accessKey, String securityKey, boolean timestampFlag, boolean nonceFlag, Map extSignHeaders, final StringBuffer signDiagnosticInfo,
                                                   String signImpl, String verifySignImpl) {
        return SignUtil.newParamsMap(paramsMap, apiName, version, accessKey, securityKey, timestampFlag, nonceFlag, extSignHeaders, signDiagnosticInfo, signImpl, verifySignImpl);
    }

    public static String trimWhiteSpaces(String value) {
        if (value == null) return value;

        return value.trim();
    }

    public static String trimUrl(String requestURL) {
        int pos = requestURL.indexOf("?");
        String ret = requestURL;

        if (pos >= 0) {
            ret = requestURL.substring(0, pos);
        }

        return ret;
    }

    public static void validateParams(String apiName, String accessKey, String securityKey, Map> paramsMap) throws HttpCallerException {
        if (apiName == null)
            throw new HttpCallerException(new InvalidParameterException("param apiName can not be null!"));

        if (accessKey != null && securityKey == null)
            throw new HttpCallerException(
                    new InvalidParameterException("param securityKey can not be null for a given accessKey!"));

        if (paramsMap != null) {
            for (Entry> kv : paramsMap.entrySet()) {
                if (kv.getValue() == null) {
                    throw new HttpCallerException(new InvalidParameterException(
                            String.format("bad parasMap, the value for key [ %s ] is null, please remove the key or set its value, e.g. \"\"!", kv.getKey())));
                }
            }
        }

    }

    private static String decodeValue(String key, String value, boolean decodeFlag) throws HttpCallerException {
        if (decodeFlag) {
            if (value == null) {
                throw new HttpCallerException("bad params, the value for key {" + key + "} is null!");
            }
            return urlDecoding(value, HTTP.UTF_8);
        }

        return value;
    }

    /**
     * Parse URL parameters to Map, url-decode all values
     *
     * @param requestURL
     * @return
     * @throws HttpCallerException
     */
    public static Map> parseUrlParamsMap(String requestURL, boolean decodeFlag) throws HttpCallerException {
        boolean questionMarkFlag = requestURL.contains("?");
        Map> urlParamsMap = new HashMap>();
        String key;
        String value;
        if (questionMarkFlag) {
            // parse params
            int pos = requestURL.indexOf("?");
            String paramStr = requestURL.substring(pos + 1);
            // requestURL = requestURL.substring(0, pos);
            // The caller needs to ensure the url-encode for a parameter value!!
            String[] params = paramStr.split("&");
            for (String param : params) {
                pos = param.indexOf("=");
                if (pos <= 0) {
                    throw new HttpCallerException("bad request URL, url params error:" + requestURL);
                }
                key = decodeValue("", param.substring(0, pos), decodeFlag);
                value = param.substring(pos + 1);
                List values = urlParamsMap.get(key);
                if (values == null) {
                    values = new ArrayList();
                }
                values.add(decodeValue(key, value, decodeFlag));
                urlParamsMap.put(key, values);
            }
        }

        return urlParamsMap;
    }
//
//	public static StringEntity jsonProcess(Map params) {
//		JSONObject jsonParam = new JSONObject();
//		for (Entry entry : params.entrySet())
//			jsonParam.put(entry.getKey(), entry.getValue());
//
//		StringEntity entity = new StringEntity(jsonParam.toString(), HTTP.UTF_8);// 解决中文乱码问题
//		entity.setContentEncoding(HTTP.UTF_8);
//		entity.setContentType("application/json");
//		return entity;
//	}

    private static void setHeaders(HttpPost httpPost, Map newParamsMap) {
        if (newParamsMap != null) {
            for (Entry kv : newParamsMap.entrySet())
                httpPost.addHeader(kv.getKey(), kv.getValue());
        }
    }


    public static void setHeaders(HttpGet httpGet, Map newParamsMap) {
        if (newParamsMap != null) {
            for (Entry kv : newParamsMap.entrySet())
                httpGet.addHeader(kv.getKey(), kv.getValue());
        }
    }

    public static String genCurlHeaders(Map newParamsMap) {
        if (newParamsMap != null) {
            StringBuffer sb = new StringBuffer();
            for (Entry kv : newParamsMap.entrySet())
                sb.append("-H \"").append(kv.getKey()).append(":").append(kv.getValue()).append("\"  ");

            return sb.toString();
        } else
            return "";
    }

    public static String createPostCurlString(String url, Map> params, Map headerParams, ContentBody cb, Map directHheaderParamsMap) {
        StringBuffer sb = new StringBuffer("curl ");

        //透传的http headers
        sb.append(genCurlHeaders(directHheaderParamsMap));

        sb.append(genCurlHeaders(headerParams));

        if (params != null) {
            StringBuffer postSB = new StringBuffer();
            for (Entry> e : params.entrySet()) {
                if (postSB.length() > 0) {
                    postSB.append("&");
                }
                for (String value : e.getValue()) {
                    postSB.append(e.getKey()).append("=").append(urlEncoding(value, HTTP.UTF_8));
                }
            }
            if (postSB.length() > 0) {
                sb.append(" -d \"");
                postSB.append("\"");
                sb.append(postSB.toString());
            } else {
                sb.append("--data ''");
            }
        } else {
            // set params as
            //FIXME need this ??
            sb.append("--data '");
            sb.append(urlEncodedString(toNVP(params), HTTP.UTF_8));
            sb.append("'");
        }

        sb.append(" --insecure ");
        sb.append("\"");
        sb.append(url);
        sb.append("\"");
        return sb.toString();
    }

    public static String urlEncoding(String str, String encoding) {
        try {
            return URLEncoder.encode(str, encoding);
        } catch (UnsupportedEncodingException e) {
            throw new IllegalArgumentException(e.getMessage(), e);
        }
    }

    public static String urlDecoding(String str, String encoding) {
        try {
            return URLDecoder.decode(str, encoding);
        } catch (UnsupportedEncodingException e) {
            throw new IllegalArgumentException(e.getMessage(), e);
        }
    }

    private static String urlEncodedString(List parameters, String charset) {
        return URLEncodedUtils.format(parameters,
                charset != null ? charset : HTTP.DEF_CONTENT_CHARSET.name());
    }

    /**
     * 只能有以下组合:
     * 1. paramsMap: paramsMap以form表单方式提交
     * 2. contentbody: 以json或二进制的 body 方式提交
     * 3. paramsMap + contentBody:  paramsMap以query方式提交,contentBody通过httpBody提交
     * 4. paramsMap + attatchFileMap: multi part的 form 方式提交
     * 5. contentbody + attatchFileMap: 暂不支持,因为http协议需要给contentBody命名
     * 6. paramsMap+ contentbody + attatchFileMap: 暂不支持,因为http协议需要给contentBody命名
     *
     * @return
     */
    public static HttpPost createPost(final String url, Map> urlParams, Map headerParams, ContentBody cb, Map fileMap, ContentEncoding contentEncoding, ContentType contentType) {
        //set both cb and urlParams
        String newUrl = url;
        List nvps = toNVP(urlParams);
        if (cb != null && urlParams != null) {
            String newParamStr = urlEncodedString(nvps, HTTP.UTF_8);
            if ("".equals(newParamStr) == false) { //避免出现最后多一个&: http://ip:port/x?y=1&
                if (!url.contains("?")) {
                    newUrl = String.format("%s?%s", url, newParamStr);
                } else {
                    newUrl = String.format("%s&%s", url, newParamStr);
                }
            }
        }

        if (contentType == null) {
            if (cb != null) { //兼容历史未让用户设置content-type的场景
                if (cb.getStrContentBody() != null) {
                    contentType = ContentType.APPLICATION_JSON.withCharset(HttpCaller.DEFAULT_CHARSET);
                } else {
                    contentType = ContentType.APPLICATION_OCTET_STREAM;
                }
            } else {
                contentType = ContentType.APPLICATION_FORM_URLENCODED.withCharset(HttpCaller.DEFAULT_CHARSET); //默认值,兼容历史
            }
        }

        HttpPost httpost = new HttpPost(newUrl);
        setHeaders(httpost, headerParams);
        if (fileMap == null || fileMap.isEmpty()) { //不是多附件请求,则要显示设置content-type。附件时,则 MultipartEntityBuilder 自动设置
            httpost.addHeader(HTTP.CONTENT_TYPE, contentType.toString());
        }

        HttpEntity entity;
        try {
            if (fileMap != null && fileMap.isEmpty() == false) { //有附件,则使用 form+附件 提交
                MultipartEntityBuilder multiBuilder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.RFC6532); //http头 始终使用utf-8,解决附件文件名中文乱码
                for (NameValuePair nvp : nvps) {
                    String name = nvp.getName();
                    String value = nvp.getValue();
                    if (contentType.getMimeType().equals(ContentType.APPLICATION_FORM_URLENCODED.getMimeType())) {
                        name = urlEncoding(nvp.getName(), contentType.getCharset().name());
                        value = urlEncoding(nvp.getValue(), contentType.getCharset().name());
                    }
                    if (ContentEncoding.gzip.equals(contentEncoding)) {
                        byte[] bytes = GZipUtils.gzipBytes(value.getBytes(HttpCaller.DEFAULT_CHARSET));
                        org.apache.http.entity.mime.content.ContentBody body = new ByteArrayBody(bytes, contentType, null);
                        FormBodyPartBuilder partBuilder = FormBodyPartBuilder.create(name, body);
                        partBuilder.setField(HTTP.CONTENT_ENCODING, GZIP);
                        multiBuilder.addPart(partBuilder.build());
                    } else {
                        multiBuilder.addTextBody(name, value, contentType);
                    }
                }

                for (Entry fileEntry : fileMap.entrySet()) {
                    HttpParameters.AttachFile file = fileEntry.getValue();
                    if (ContentEncoding.gzip.equals(file.getContentEncoding())) { //对附件进行压缩
                        FormBodyPartBuilder partBuilder = FormBodyPartBuilder.create(fileEntry.getKey(), new ByteArrayBody(GZipUtils.gzipBytes(file.getFileBytes()), file.getFileName()));
                        partBuilder.setField(HTTP.CONTENT_ENCODING, GZIP);
                        multiBuilder.addPart(partBuilder.build());
                    } else {
                        multiBuilder.addBinaryBody(fileEntry.getKey(), file.getFileBytes(), ContentType.DEFAULT_BINARY, file.getFileName());
                    }
                }
                entity = multiBuilder.build();
            } else if (cb == null) { //无附件,无body内容,则使用form提交
                entity = new UrlEncodedFormEntity(nvps, HTTP.UTF_8);
                if (ContentEncoding.gzip.equals(contentEncoding)) {
                    entity = new GzipCompressingEntity(entity);
                    httpost.setHeader(HTTP.CONTENT_ENCODING, GZIP);
                }
            } else {
                if (ContentEncoding.gzip.equals(contentEncoding)) {
                    httpost.setHeader(HTTP.CONTENT_ENCODING, GZIP); //不参与签名,因为服务端需要先解析这个头,然后才参获得实际内容。同时兼容历史版本
                }

                if (cb.getStrContentBody() != null) {  //无附件,有json body内容,则 application/json 方式提交
                    entity = new StringEntity(cb.getStrContentBody(), contentType);// 解决中文乱码问题
                    if (ContentEncoding.gzip.equals(contentEncoding)) {
                        entity = new GzipCompressingEntity(entity);
                    }
                } else {  //无附件,有二进制body内容,则 APPLICATION_OCTET_STREAM 方式提交
                    entity = new ByteArrayEntity(cb.getBytesContentBody(), contentType);
                    if (ContentEncoding.gzip.equals(contentEncoding)) {
                        entity = new GzipCompressingEntity(entity);
                    }
                }
            }

            httpost.setEntity(entity);
        } catch (UnsupportedEncodingException e) {
            throw new IllegalArgumentException(e.getMessage(), e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return httpost;
    }

    private static List toNVP(Map> urlParams) {
        List nvps = new ArrayList();

        //fix NPE
        if (urlParams != null) {
            Set keySet = urlParams.keySet();
            for (String key : keySet) {
                for (String value : urlParams.get(key)) {
                    nvps.add(new BasicNameValuePair(key, value));
                }
            }
        }
        return nvps;
    }

    public static void setDirectHeaders(HttpPost httpPost, Map directHheaderParamsMap) {
        if (directHheaderParamsMap == null) {
            //do nothing
            return;
        } else {
            for (Entry kv : directHheaderParamsMap.entrySet()) {
                if (kv.getKey() == null) {
                    //log.info("ignore empty key");
                } else {
                    if (HTTP.CONTENT_TYPE.equals(kv.getKey()) || !httpPost.containsHeader(kv.getKey())) {
                        // direct header has no chance to overwrite the normal headers, except it is the content-type
                        httpPost.addHeader(kv.getKey(), kv.getValue());
                    }
                }
            }
        }
    }

    public static String getUrlPathInfo(String url) throws HttpCallerException {
        URL urlStr = null;
        try {
            urlStr = new URL(url);
        } catch (Exception e) {
            throw new HttpCallerException("url is unformat, url is " + url);
        }
        String path = urlStr.getPath();
        return path;
    }

    public static Map fetchResHeaderMap(final HttpResponse response) {
        Map headerMap = new HashMap();
        if (response != null) {
            headerMap.put("HTTP-STATUS", String.valueOf(response.getStatusLine().getStatusCode()));
            for (Header header : response.getAllHeaders()) {
                headerMap.put(header.getName(), header.getValue());
            }
        }

        return headerMap;
    }

    public static String fetchResHeaders(final HttpResponse response) {
        if (response != null) {
            StringBuffer body = new StringBuffer();
            //add response http status
            body.append(String.format("\"%s\":\"%s\"", "HTTP-STATUS", response.getStatusLine()));
            for (Header header : response.getAllHeaders()) {
                if (body.length() > 0)
                    body.append(",");
                body.append(String.format("\"%s\":\"%s\"", header.getName(), header.getValue()));
            }
            return String.format("{%s}", body.toString());
        }

        return null;
    }


    public static String generateAsEncodeRequestUrl(String requestURL, Map> urlParamsMap) {
        requestURL = HttpClientHelper.trimUrl(requestURL);

        StringBuffer params = new StringBuffer();
        for (Entry> kv : urlParamsMap.entrySet()) {
            if (params.length() > 0) {
                params.append("&");
            }
            if (kv.getValue() != null) {
                List vlist = kv.getValue();
                for (String v : vlist) {
                    params.append(urlEncoding(kv.getKey(), HTTP.UTF_8)).append("=").append(urlEncoding(v, HTTP.UTF_8));
                }
            }
        }

        String newRequestURL = requestURL;
        if (params.length() > 0)
            newRequestURL += "?" + params.toString();

        HttpClientHelper.printDebugInfo("-- requestURL=" + newRequestURL);
        return newRequestURL;
    }

    public static String getParamsUrlEncodingStr(Map> params) {
        StringBuffer sb = new StringBuffer();
        if (params != null) {
            for (Entry> e : params.entrySet()) {
                for (String value : e.getValue()) {
                    sb.append("&").append(urlEncoding(e.getKey(), HTTP.UTF_8)).append("=").append(urlEncoding(value, HTTP.UTF_8));
                }
            }
        }
        if (sb.length() > 0) {
            return sb.toString().substring(1); //去掉最前面的 &
        } else {
            return "";
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy