SpringCloud Gateway 获取 request body response write
发表于:2024-11-25 作者:热门IT资讯网编辑
编辑最后更新 2024年11月25日,话不多说,直接上码/** * @author liuhanling * @create 2018-12-14 20:01 * @desc */@Slf4j@Componentpublic class
话不多说,直接上码
/** * @author liuhanling * @create 2018-12-14 20:01 * @desc */@Slf4j@Componentpublic class RequestBodyFilter implements GatewayFilter, Ordered { private static final String CACHE_REQUEST_BODY_OBJECT_KEY = "cachedRequestBodyObject"; @Override @SuppressWarnings("unchecked") public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { Class inClass = String.class; ServerRequest serverRequest = new DefaultServerRequest(exchange); ServerHttpRequest request = exchange.getRequest(); //只记录 http 请求(包含 https) String schema = request.getURI().getScheme(); if ((!"http".equals(schema) && !"https".equals(schema))) { return chain.filter(exchange); } String contentType = request.getHeaders().getFirst("Content-Type"); String upload = request.getHeaders().getFirst("upload"); //get 方法获取参数 if ("GET".equals(request.getMethod().name())) { if (!request.getQueryParams().isEmpty()) { Map map = new HashMap<>(); request.getQueryParams().toSingleValueMap().forEach((key, val) -> map.put(key, getURLDecoder(val))); String param = new Gson().toJson(map); exchange.getAttributes().put(CACHE_REQUEST_BODY_OBJECT_KEY, param); } return chain.filter(exchange); } //没有内容类型不读取body if (contentType == null || contentType.length() == 0) { return chain.filter(exchange); } //文件上传不读取body if ("true".equals(upload)) { return chain.filter(exchange); } Mono> modifiedBody = serverRequest.bodyToMono(inClass).flatMap(o -> { log.debug("requestBody:{}", o); exchange.getAttributes().put(CACHE_REQUEST_BODY_OBJECT_KEY, o); return Mono.justOrEmpty(o); }); BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, inClass); HttpHeaders headers = new HttpHeaders(); headers.putAll(exchange.getRequest().getHeaders()); CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers); return bodyInserter.insert(outputMessage, new BodyInserterContext()) .then(Mono.defer(() -> { ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(exchange.getRequest()) { @Override public HttpHeaders getHeaders() { long contentLength = headers.getContentLength(); HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.putAll(super.getHeaders()); if (contentLength > 0) { httpHeaders.setContentLength(contentLength); } else { // TODO: this causes a 'HTTP/1.1 411 Length Required' on httpbin.org httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked"); } return httpHeaders; } @Override public Flux getBody() { return outputMessage.getBody(); } }; return chain.filter(exchange.mutate().request(decorator).build()); })); } @Override public int getOrder() { return 0; } /** * URL 转码 * @param val * @return */ private String getURLDecoder(String val){ try{ return URLDecoder.decode(val, "utf-8"); }catch (Exception e){ log.error("getURLDecoder error",e); } return val; }}
重写 ResponseBody
/** * @author liuhanling * @create 2018-12-27 10:39 * @desc */@Component@Slf4jpublic class ResponseBodyFilter implements GatewayFilter, Ordered { @Override @SuppressWarnings("unchecked") public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpResponseDecorator responseDecorator = new ServerHttpResponseDecorator(exchange.getResponse()) { @Override public Mono writeWith(Publisher extends DataBuffer> body) { Class inClass = String.class; Class outClass = String.class; String originalResponseContentType = exchange.getAttribute(ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR); HttpHeaders httpHeaders = new HttpHeaders(); //explicitly add it in this way instead of 'httpHeaders.setContentType(originalResponseContentType)' //this will prevent exception in case of using non-standard media types like "Content-Type: image" httpHeaders.add(HttpHeaders.CONTENT_TYPE, originalResponseContentType); ResponseAdapter responseAdapter = new ResponseAdapter(body, httpHeaders); DefaultClientResponse clientResponse = new DefaultClientResponse(responseAdapter, ExchangeStrategies.withDefaults()); //TODO: flux or mono Mono modifiedBody = clientResponse.bodyToMono(inClass) .flatMap(originalBody -> { //如果是文件 Gson gson = new Gson(); Map res = gson.fromJson(String.valueOf(originalBody),new TypeToken>() {}.getType()); //修改 res.put("test_id",UUID.randomUUID().toString().replace("-","")); return Mono.just(gson.toJson(res)); }); BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, outClass); CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, exchange.getResponse().getHeaders()); return bodyInserter.insert(outputMessage, new BodyInserterContext()) .then(Mono.defer(() -> { Flux messageBody = outputMessage.getBody(); //TODO: if (inputStream instanceof Mono) { HttpHeaders headers = getDelegate().getHeaders(); if (!headers.containsKey(HttpHeaders.TRANSFER_ENCODING)) { messageBody = messageBody.doOnNext(data -> headers.setContentLength(data.readableByteCount())); } // } //TODO: use isStreamingMediaType? return getDelegate().writeWith(messageBody); })); } @Override public Mono writeAndFlushWith(Publisher extends Publisher extends DataBuffer>> body) { return writeWith(Flux.from(body) .flatMapSequential(p -> p)); } }; return chain.filter(exchange.mutate().response(responseDecorator).build()); } @Override public int getOrder() { return 0; } public class ResponseAdapter implements ClientHttpResponse { private final Flux flux; private final HttpHeaders headers; public ResponseAdapter(Publisher extends DataBuffer> body, HttpHeaders headers) { this.headers = headers; if (body instanceof Flux) { flux = (Flux) body; } else { flux = ((Mono)body).flux(); } } @Override public Flux getBody() { return flux; } @Override public HttpHeaders getHeaders() { return headers; } @Override public HttpStatus getStatusCode() { return null; } @Override public int getRawStatusCode() { return 0; } @Override public MultiValueMap getCookies() { return null; } }}
版本信息
org.springframework.boot spring-boot-starter-parent 2.0.2.RELEASE UTF-8 UTF-8 1.8 Finchley.SR2
理论部分参考: https://blog.51cto.com/thinklili/2329184