潘志宝
2024-12-23 5bf42aa9950058f391805e6fb8d7376f4378924b
提交 | 用户 | 时间
e7c126 1 package com.iailab.gateway.util;
H 2
3 import cn.hutool.core.net.NetUtil;
4 import cn.hutool.core.util.ArrayUtil;
5 import cn.hutool.core.util.NumberUtil;
6 import cn.hutool.extra.servlet.ServletUtil;
7 import com.iailab.framework.common.util.json.JsonUtils;
8 import lombok.extern.slf4j.Slf4j;
9 import org.springframework.cloud.gateway.route.Route;
10 import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
11 import org.springframework.core.io.buffer.DataBufferFactory;
12 import org.springframework.http.HttpHeaders;
13 import org.springframework.http.MediaType;
14 import org.springframework.http.server.reactive.ServerHttpRequest;
15 import org.springframework.http.server.reactive.ServerHttpResponse;
16 import org.springframework.web.server.ServerWebExchange;
17 import reactor.core.publisher.Mono;
18
19 /**
20  * Web 工具类
21  *
22  * copy from iailab-common-web 的 WebFrameworkUtils 类
23  *
24  * @author iailab
25  */
26 @Slf4j
27 public class WebFrameworkUtils {
28
29     private static final String HEADER_TENANT_ID = "tenant-id";
30
31     private WebFrameworkUtils() {}
32
33     /**
34      * 将 Gateway 请求中的 header,设置到 HttpHeaders 中
35      *
36      * @param tenantId 租户编号
37      * @param httpHeaders WebClient 的请求
38      */
39     public static void setTenantIdHeader(Long tenantId, HttpHeaders httpHeaders) {
40         if (tenantId == null) {
41             return;
42         }
43         httpHeaders.set(HEADER_TENANT_ID, String.valueOf(tenantId));
44     }
45
46     public static Long getTenantId(ServerWebExchange exchange) {
47         String tenantId = exchange.getRequest().getHeaders().getFirst(HEADER_TENANT_ID);
48         return NumberUtil.isNumber(tenantId) ? Long.valueOf(tenantId) : null;
49     }
50
51     /**
52      * 返回 JSON 字符串
53      *
54      * @param exchange 响应
55      * @param object 对象,会序列化成 JSON 字符串
56      */
57     @SuppressWarnings("deprecation") // 必须使用 APPLICATION_JSON_UTF8_VALUE,否则会乱码
58     public static Mono<Void> writeJSON(ServerWebExchange exchange, Object object) {
59         // 设置 header
60         ServerHttpResponse response = exchange.getResponse();
61         response.getHeaders().setContentType(MediaType.APPLICATION_JSON_UTF8);
62         // 设置 body
63         return response.writeWith(Mono.fromSupplier(() -> {
64             DataBufferFactory bufferFactory = response.bufferFactory();
65             try {
66                 return bufferFactory.wrap(JsonUtils.toJsonByte(object));
67             } catch (Exception ex) {
68                 ServerHttpRequest request = exchange.getRequest();
69                 log.error("[writeJSON][uri({}/{}) 发生异常]", request.getURI(), request.getMethod(), ex);
70                 return bufferFactory.wrap(new byte[0]);
71             }
72         }));
73     }
74
75     /**
76      * 获得客户端 IP
77      *
78      * 参考 {@link ServletUtil} 的 getClientIP 方法
79      *
80      * @param exchange 请求
81      * @param otherHeaderNames 其它 header 名字的数组
82      * @return 客户端 IP
83      */
84     public static String getClientIP(ServerWebExchange exchange, String... otherHeaderNames) {
85         String[] headers = { "X-Forwarded-For", "X-Real-IP", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR" };
86         if (ArrayUtil.isNotEmpty(otherHeaderNames)) {
87             headers = ArrayUtil.addAll(headers, otherHeaderNames);
88         }
89         // 方式一,通过 header 获取
90         String ip;
91         for (String header : headers) {
92             ip = exchange.getRequest().getHeaders().getFirst(header);
93             if (!NetUtil.isUnknown(ip)) {
94                 return NetUtil.getMultistageReverseProxyIp(ip);
95             }
96         }
97
98         // 方式二,通过 remoteAddress 获取
99         if (exchange.getRequest().getRemoteAddress() == null) {
100             return null;
101         }
102         ip = exchange.getRequest().getRemoteAddress().getHostString();
103         return NetUtil.getMultistageReverseProxyIp(ip);
104     }
105
106     /**
107      * 获得请求匹配的 Route 路由
108      *
109      * @param exchange 请求
110      * @return 路由
111      */
112     public static Route getGatewayRoute(ServerWebExchange exchange) {
113         return exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
114     }
115
116 }