package com.feifan.aida.gateway.filter;
import cn.hutool.json.JSONObject;
import com.alibaba.fastjson.JSON;
import com.feifan.aida.gateway.common.AidaConstant;
import com.feifan.aida.gateway.common.RandomUtils;
import io.netty.buffer.ByteBufAllocator;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.NettyDataBufferFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import redis.clients.jedis.JedisCluster;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.nio.charset.StandardCharsets;
/***
*
*
* 获取请求参数RequestBody
*
* */
@Slf4j
//@Component
public class HttpRequestFilter implements GlobalFilter, Ordered {
private JedisCluster jedisCluster;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String contentType = request.getHeaders().getFirst("Content-Type");
return DataBufferUtils.join(exchange.getRequest().getBody())
.flatMap(dataBuffer -> {
byte[] bytes = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(bytes);
//释放堆外内存 不然会有内存泄漏
DataBufferUtils.release(dataBuffer);
try {
String bodyString = new String(bytes, "utf-8");
//修改测试
com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(bodyString);
com.alibaba.fastjson.JSONObject user = jsonObject.getJSONObject("user");
Long wid = user.getLong("wid");
user.put("group","B");
bodyString = com.alibaba.fastjson.JSONObject.toJSONString(jsonObject);
URI uri = request.getURI();
URI newUri = UriComponentsBuilder.fromUri(uri).build(true).toUri();
log.info(newUri.getPath());
ServerHttpRequest serverHttpRequest = exchange.getRequest().mutate().uri(newUri).build();
DataBuffer bodyDataBuffer = stringBuffer(bodyString);
Flux<DataBuffer> bodyFlux = Flux.just(bodyDataBuffer);
// 定义新的消息头
HttpHeaders headers = new HttpHeaders();
headers.putAll(exchange.getRequest().getHeaders());
// 由于修改了传递参数,需要重新设置CONTENT_LENGTH,长度是字节长度,不是字符串长度
int length = bodyString.getBytes().length;
headers.remove(HttpHeaders.CONTENT_LENGTH);
headers.setContentLength(length);
// 设置CONTENT_TYPE
if (StringUtils.isNotBlank(contentType)) {
headers.set(HttpHeaders.CONTENT_TYPE, contentType);
}
serverHttpRequest = new ServerHttpRequestDecorator(serverHttpRequest) {
@Override
public HttpHeaders getHeaders() {
long contentLength = headers.getContentLength();
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.putAll(super.getHeaders());
if (contentLength > 0) {
httpHeaders.setContentLength(contentLength);
} else {
httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
}
return httpHeaders;
}
@Override
public Flux<DataBuffer> getBody() {
return bodyFlux;
}
};
//封装request,传给下一级
serverHttpRequest.mutate().header(HttpHeaders.CONTENT_LENGTH, Integer.toString(bodyString.length()));
return chain.filter(exchange.mutate().request(serverHttpRequest).build());
//exchange.getAttributes().put("POST_BODY", bodyString);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
DataBufferUtils.release(dataBuffer);
Flux<DataBuffer> cachedFlux = Flux.defer(() -> {
DataBuffer buffer = exchange.getResponse().bufferFactory()
.wrap(bytes);
return Mono.just(buffer);
});
ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(
exchange.getRequest()) {
@Override
public Flux<DataBuffer> getBody() {
return cachedFlux;
}
};
return chain.filter(exchange.mutate().request(mutatedRequest)
.build());
});
}
@Override
public int getOrder() {
return 0;
}
/**
* 是否存在
* @param wid
* @param userJSONObject
*/
private void existsAB(String wid, JSONObject userJSONObject){
String userGroup = jedisCluster.get(AidaConstant.AB_REDIS_USER_GROUP+"_"+wid);
//判断
if(StringUtils.equals(userGroup,AidaConstant.A_REDIS_USER_GROUP)){
userJSONObject.put("group","A");
}else if(StringUtils.equals(userGroup,AidaConstant.B_REDIS_USER_GROUP)){
userJSONObject.put("group","B");
}
}
private void isNotExistsAB(String wid, JSONObject userJSONObject){
if(RandomUtils.nextBoolean()){
//随机分配A组人群
jedisCluster.incr(AidaConstant.A_REDIS_USER_GROUP);
jedisCluster.set(AidaConstant.AB_REDIS_USER_GROUP+"_"+wid,AidaConstant.A_REDIS_USER_GROUP);
userJSONObject.put("group","A");
}else{
//随机分配B组人群
jedisCluster.incr(AidaConstant.B_REDIS_USER_GROUP);
jedisCluster.set(AidaConstant.AB_REDIS_USER_GROUP+"_"+wid,AidaConstant.B_REDIS_USER_GROUP);
userJSONObject.put("group","B");
}
}
private DataBuffer stringBuffer(String value) {
byte[] bytes = value.getBytes(StandardCharsets.UTF_8);
NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);
DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length);
buffer.write(bytes);
return buffer;
}
}