gateway过滤器获取请求参数及打印

第一个过滤器

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
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.*;
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 reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@Component
public class RequestParamsFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String method = request.getMethodValue();
if ("POST".equals(method)) {
//如果body里空,这三行代码不能省
DefaultDataBufferFactory defaultDataBufferFactory = new DefaultDataBufferFactory();
DefaultDataBuffer defaultDataBuffer = defaultDataBufferFactory.allocateBuffer(0);
Mono<DataBuffer> mono = Flux.from(exchange.getRequest().getBody().defaultIfEmpty(defaultDataBuffer)).collectList().filter(list -> true).map(list -> list.get(0).factory().join(list)).doOnDiscard(PooledDataBuffer.class, DataBufferUtils::release);
//读取后重新封装请求
return mono.flatMap(dataBuffer -> {
byte[] bytes = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(bytes);
DataBufferUtils.release(dataBuffer);
String body = new String(bytes, StandardCharsets.UTF_8);
exchange.getAttributes().put("MY_PAYLOAD", body);
//这是必须要重新封装一个请求, 因为body只能读一次,下游将无法读取,真操蛋
Flux<DataBuffer> cachedFlux = Flux.defer(() -> {
DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes);
return Mono.just(buffer);
});
ServerHttpRequest newRequest = new ServerHttpRequestDecorator(request) {
@Override
public Flux<DataBuffer> getBody() {
return cachedFlux;
}
};
return chain.filter(exchange.mutate().request(newRequest).build());
});
} else if ("GET".equals(method)) {
if("GET".equals(method)){
Map<String, String> params = new HashMap<>();
request.getQueryParams().forEach((k,v)-> params.put(k, v.get(0)));
exchange.getAttributes().put("MY_PAYLOAD", JSON.toJSONString(params));
}
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
}
}

第二个过滤器

private ServerHttpResponse getResponse(ServerWebExchange exchange, boolean isValid, String path, GatewayRequestHeader headerObj){
long sts = System.currentTimeMillis();
ServerHttpResponse response = exchange.getResponse();
DataBufferFactory bufferFactory = response.bufferFactory();
ServerHttpResponseDecorator responseNew = new ServerHttpResponseDecorator(response) {
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
if (getStatusCode().equals(HttpStatus.OK) && body instanceof Flux) {
String originalResponseContentType = exchange.getAttribute(ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR);
if (StringUtils.isNotBlank(originalResponseContentType) && originalResponseContentType.contains("application/json")) {
Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
String resp;
if(isValid){
//DefaultDataBufferFactory join 乱码的问题解决
DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
DataBuffer join = dataBufferFactory.join(dataBuffers);
// probably should reuse buffers
byte[] content = new byte[join.readableByteCount()];
join.read(content);
//释放掉内存
DataBufferUtils.release(join);
resp = new String(content, StandardCharsets.UTF_8);
}else {
Map<String, Object> map = new HashMap<>();
map.put("code", "401");
map.put("message", "UNAUTHORIZED");
resp = JSON.toJSONString(map);
}
logPrint(exchange, path, resp, sts, headerObj);
return bufferFactory.wrap(resp.getBytes());
}));
}
}
logPrint(exchange, path, "", sts, headerObj);
return super.writeWith(body);
}
};
return responseNew;
}
@Override
public int getOrder() {
return -2;
}
posted @   码农记事本  阅读(535)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示