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

com.feingto.cloud.kit.HttpKit Maven / Gradle / Ivy

There is a newer version: 2.5.2.RELEASE
Show newest version
package com.feingto.cloud.kit;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.feingto.cloud.kit.json.JSON;
import lombok.SneakyThrows;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.util.*;
import org.springframework.web.util.UriTemplate;
import org.springframework.web.util.UriUtils;

import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.URI;
import java.net.URLDecoder;
import java.net.UnknownHostException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.springframework.http.HttpHeaders.CONTENT_TYPE;

/**
 * Http 工具类
 *
 * @author longfei
 */
public class HttpKit {
    public static final PathMatcher pathMatcher = new AntPathMatcher();

    /**
     * 根据 scheme, address, post 生成URL
     *
     * @param scheme  http scheme
     * @param address 主机地址
     * @param port    端口
     */
    public static String getUrl(String scheme, String address, int port) {
        return String.format("%s://%s:%s", scheme, address, port);
    }

    /**
     * 根据 scheme, address, post 生成已编码URL
     *
     * @param scheme  http scheme
     * @param address 主机地址
     * @param port    端口
     */
    public static String getEncodeUrl(String scheme, String address, int port) {
        return UriUtils.encodePath(getUrl(scheme, address, port), UTF_8);
    }

    /**
     * 获取主机域 Scheme + 域名
     *
     * @param target url
     */
    public static String getHostname(String target) {
        URI uri = URI.create(target);
        return uri.getScheme().concat("://").concat(uri.getHost());
    }

    /**
     * 根据正则获取主机域 Scheme + 域名
     *
     * @param target url
     */
    public static String getHostname(String target, String regex) {
        Matcher matcher = Pattern.compile(regex).matcher(target);
        return matcher.find() ? matcher.group(0) : target;
    }

    /**
     * Map转多值Map
     *
     * @param map MultiValueMap
     */
    public static MultiValueMap toMultiValueMap(Map map) {
        MultiValueMap multiMap = new LinkedMultiValueMap<>();
        map.forEach(multiMap::set);
        return multiMap;
    }

    /**
     * 是否包含指定媒体类型
     *
     * @param headers    HttpHeaders
     * @param mediaTypes MediaType
     */
    public static boolean isMediaType(HttpHeaders headers, MediaType... mediaTypes) {
        return Optional.ofNullable(headers.getFirst(CONTENT_TYPE))
                .map(MediaType::valueOf)
                .map(mediaType -> Arrays.stream(mediaTypes)
                        .anyMatch(media -> media.includes(mediaType)))
                .orElse(false);
    }

    /**
     * 获取参数查询字符串
     *
     * @param queryParams 查询参数
     * @return query string
     */
    public static String getQueryString(MultiValueMap queryParams) {
        if (queryParams.isEmpty()) {
            return "";
        }

        StringBuilder query = new StringBuilder();
        Map singles = new HashMap<>();

        for (String param : queryParams.keySet()) {
            int i = 0;
            for (String value : queryParams.get(param)) {
                query.append("&");
                query.append(param);
                if (!"".equals(value)) {
                    String key = param;
                    if (key.contains("\f")) {
                        key = (Pattern.compile("\f").matcher(key).replaceAll("\f\f"));
                    }
                    if (key.contains(":")) {
                        key = Pattern.compile(":").matcher(key).replaceAll("\f");
                    }
                    key = key + i;
                    singles.put(key, value);
                    query.append("={");
                    query.append(key);
                    query.append("}");
                }
                i++;
            }
        }

        UriTemplate template = new UriTemplate(query.toString().substring(1));
        return template.expand(singles).toString();
    }

    /**
     * 获取查询字符串的参数Map
     *
     * @param queryString 查询字符串
     * @return 查询参数Map
     */
    @SneakyThrows
    public static Map> getQueryParams(String queryString) {
        if (StringUtils.isEmpty(queryString)) {
            return new HashMap<>();
        }

        Map> queryParams = new LinkedMultiValueMap<>();
        StringTokenizer tokenizer = new StringTokenizer(queryString, "&");

        int i;
        while (tokenizer.hasMoreTokens()) {
            String token = tokenizer.nextToken();
            i = token.indexOf("=");
            if (i > 0 && token.length() >= i + 1) {
                String name = URLDecoder.decode(token.substring(0, i), UTF_8.name());
                String value = URLDecoder.decode(token.substring(i + 1), UTF_8.name());
                List valueList = queryParams.computeIfAbsent(name, k -> new LinkedList<>());
                valueList.add(value);
            } else if (i == -1) {
                String name = URLDecoder.decode(token, UTF_8.name());
                String value = "";
                List valueList = queryParams.computeIfAbsent(name, k -> new LinkedList<>());
                valueList.add(value);
            }
        }

        return queryParams;
    }

    /**
     * 追加 query string
     *
     * @param originalQuery 原有查询参数字符串
     * @param appendQuery   追加的查询参数字符串
     */
    public static String appendQueryString(String originalQuery, String appendQuery) {
        StringBuilder query = new StringBuilder();

        if (StringUtils.hasLength(originalQuery)) {
            query.append(originalQuery);
            if (originalQuery.charAt(originalQuery.length() - 1) != '&' && StringUtils.hasLength(appendQuery)) {
                query.append('&');
            }
        }

        if (appendQuery.startsWith("?") || appendQuery.startsWith("&")) {
            appendQuery = appendQuery.substring(1);
        }

        return query.toString() + appendQuery;
    }

    /**
     * request body 字符串追加参数Map
     *
     * @param requestBody request body
     * @param parameters  参数Map
     */
    public static ObjectNode appendParamsToBody(String requestBody, MultiValueMap parameters) {
        ObjectNode objectNode = (ObjectNode) JSON.read(requestBody);
        parameters.forEach((key, values) -> {
            ArrayNode arrayNode = JSON.JSONArray();
            values.forEach(arrayNode::add);
            objectNode.putPOJO(key, arrayNode);
        });
        return objectNode;
    }

    /**
     * Json 对象节点递归遍历转换参数Map
     *
     * @param node       JsonNode
     * @param parameters MultiValueMap
     */
    public static void jsonNodeRecursiveToMap(JsonNode node, MultiValueMap parameters) {
        if (node.isValueNode()) {
            return;
        }

        if (node.isObject()) {
            Iterator> it = node.fields();
            while (it.hasNext()) {
                Map.Entry entry = it.next();
                if (entry.getValue().isArray()) {
                    parameters.add(entry.getKey(), entry.getValue().toString());
                } else {
                    parameters.set(entry.getKey(), entry.getValue().toString());
                }
                jsonNodeRecursiveToMap(entry.getValue(), parameters);
            }
        }

        if (node.isArray()) {
            for (JsonNode it : node) {
                jsonNodeRecursiveToMap(it, parameters);
            }
        }
    }

    /**
     * 是否 URI 模板
     *
     * @param uriTemplate the URI template string
     */
    public static boolean isUriTemplate(String uriTemplate) {
        return uriTemplate.contains("{") && uriTemplate.contains("}");
    }

    /**
     * 提取URI模板变量, URI模板变量通过大括号('{'和'}')表示
     * example: For pattern "/api/v1/test/{id}" and path "/api/v1/test/1", this method will
     *
     * @param pattern 请求路径表达式
     * @param path    请求路径
     * @return a map containing "id"->"1".
     */
    public static Map extractUriTemplate(String pattern, String path) {
        return pathMatcher.extractUriTemplateVariables(pattern, EncodeKit.urlDecode(path));
    }

    /**
     * 解析包含URI模板变量的路径, URI模板变量通过大括号('{'和'}')表示
     * example: For pattern "/api/v1/test/{id}" and id "1" -> path "/api/v1/test/1"
     *
     * @param path                 请求路径
     * @param uriTemplateVariables URI模板参数
     * @return url
     */
    public static String combineUriTemplate(String path, Map uriTemplateVariables) {
        if (MapUtils.isEmpty(uriTemplateVariables)) {
            return path;
        }
        for (String key : uriTemplateVariables.keySet()) {
            path = path.replace("{" + key + "}", uriTemplateVariables.get(key));
        }
        return path;
    }

    /**
     * 解析包含参数模板变量的路径, 参数模板变量通过井号('#'和'#')表示
     * example: For pattern "#path#/test" and #path#: "/api/v1" -> path "/api/v1/test"
     *
     * @param path                   请求路径
     * @param paramTemplateVariables 参数模板
     * @return url
     */
    public static String combineEnvTemplate(String path, List paramTemplateVariables) {
        if (CollectionUtils.isEmpty(paramTemplateVariables)) {
            return path;
        }
        for (KeyValue keyValue : paramTemplateVariables) {
            path = path.replace("#" + keyValue.getKey() + "#", keyValue.getValue().toString());
        }
        return path;
    }

    /**
     * 判断是否Ajax请求
     *
     * @param request HttpServletRequest
     */
    public static boolean isAjaxWithRequest(HttpServletRequest request) {
        if (Objects.isNull(request)) {
            return false;
        }
        return Objects.isNull(request.getHeader("X-Requested-With")) ?
                MediaType.ALL_VALUE.equals(request.getHeader(HttpHeaders.ACCEPT)) ||
                        StringUtils.hasText(request.getHeader(HttpHeaders.ACCEPT)) &&
                                request.getHeader(HttpHeaders.ACCEPT).contains(MediaType.APPLICATION_JSON_VALUE) :
                request.getHeader("X-Requested-With").equals("XMLHttpRequest");
    }

    /**
     * 获取当前网络ip
     *
     * @param request HttpServletRequest
     */
    public static String getIpAddr(HttpServletRequest request) {
        return getIpAddr(request, null);

    }

    /**
     * 获取当前网络ip
     *
     * @param request HttpServletRequest
     */
    public static String getIpAddr(HttpServletRequest request, String headerName) {
        if (StringUtils.isEmpty(headerName)) {
            headerName = "X-Forwarded-For";
        }
        String ipAddress = request.getHeader(headerName);
        if (StringUtils.isEmpty(ipAddress)) {
            ipAddress = request.getRemoteAddr();
            // 根据网卡取本机配置的IP
            if (ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")) {
                try {
                    ipAddress = InetAddress.getLocalHost().getHostAddress();
                } catch (UnknownHostException ignored) {
                }
            }
        }
        // 对于通过多个代理的情况, 第一个IP为客户端真实IP, 多个IP按照','分割
        if (Objects.nonNull(ipAddress) && ipAddress.contains(",")) {
            ipAddress = ipAddress.split(",")[0];
        }
        return ipAddress;
    }

    /**
     * 获取浏览器类型
     *
     * @param request HttpServletRequest
     */
    public static String getBrowser(HttpServletRequest request) {
        String browser = "未知";
        if (Objects.nonNull(request)) {
            try {
                String ua = getUserAgent(request);
                int idx;
                if (ua.contains("MSIE")) {
                    idx = ua.indexOf("MSIE");
                    browser = ua.substring(idx, ua.indexOf(";", idx));
                } else if (ua.contains("Edge/")) {
                    idx = ua.indexOf("Edge/");
                    browser = ua.substring(idx);
                } else if (ua.contains("gecko") && ua.contains("rv:11.0")) {
                    browser = "MSIE 11.0";
                } else if (ua.contains("OPR/")) {
                    idx = ua.indexOf("OPR/");
                    browser = ua.substring(idx);
                    browser = browser.replace("OPR", "Opera");
                } else if (ua.contains("Chrome/")) {
                    idx = ua.indexOf("Chrome");
                    browser = ua.substring(idx, ua.indexOf(" ", idx));
                } else if (ua.contains("Firefox/")) {
                    idx = ua.indexOf("Firefox/");
                    browser = ua.substring(idx);
                } else if (ua.contains("Safari/")) {
                    idx = ua.indexOf("Safari/");
                    browser = ua.substring(idx);
                }
            } catch (Exception e) {
                browser = "未知";
            }
        }
        return browser;
    }

    /**
     * 获取操作系统
     *
     * @param request HttpServletRequest
     */
    public static String getPlatform(HttpServletRequest request) {
        String platform = "未知";
        if (Objects.nonNull(request)) {
            String ua = getUserAgent(request);
            if (ua.contains("Windows Phone")) {
                platform = "Windows Phone";
            } else if (ua.contains("Windows")) {
                platform = "Windows";
                if (ua.contains("Windows NT 10.0")) {
                    platform = "Windows 10";
                } else if (ua.contains("Windows NT 6.3")) {
                    platform = "Windows 8.1";
                } else if (ua.contains("Windows NT 6.2")) {
                    platform = "Windows 8";
                } else if (ua.contains("Windows NT 6.1")) {
                    platform = "Windows 7";
                } else if (ua.contains("Windows NT 6.0")) {
                    platform = "Windows Vista";
                } else if (ua.contains("Windows NT 5.1")) {
                    platform = "Windows XP";
                }
            } else if (ua.contains("iPad")) {
                platform = "iPad";
            } else if (ua.contains("iPhone")) {
                platform = "iPhone";
            } else if (ua.contains("Android")) {
                platform = "Android";
            } else if (ua.contains("Linux")) {
                platform = "Linux";
            }
        }
        return platform;
    }

    /**
     * 获取用户代理
     *
     * @param request HttpServletRequest
     */
    private static String getUserAgent(HttpServletRequest request) {
        return Objects.nonNull(request)
                ? request.getHeader(HttpHeaders.USER_AGENT)
                : "";
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy