温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

SpringCloud Gateway 获取 request body response write

发布时间:2020-06-16 10:06:11 来源:网络 阅读:7866 作者:liuhanling 栏目:软件技术

话不多说,直接上码

/** * @author liuhanling * @create 2018-12-14 20:01 * @desc */ @Slf4j @Component public class RequestBodyFilter implements GatewayFilter, Ordered { private static final String CACHE_REQUEST_BODY_OBJECT_KEY = "cachedRequestBodyObject"; @Override @SuppressWarnings("unchecked") public Mono<Void> 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<String, String> 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<DataBuffer> 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 @Slf4j public class ResponseBodyFilter implements GatewayFilter, Ordered { @Override @SuppressWarnings("unchecked") public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpResponseDecorator responseDecorator = new ServerHttpResponseDecorator(exchange.getResponse()) { @Override public Mono<Void> 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<String,String> res = gson.fromJson(String.valueOf(originalBody),new TypeToken<HashMap<String, String>>() {}.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<DataBuffer> 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<Void> 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<DataBuffer> 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<DataBuffer> getBody() { return flux; } @Override public HttpHeaders getHeaders() { return headers; } @Override public HttpStatus getStatusCode() { return null; } @Override public int getRawStatusCode() { return 0; } @Override public MultiValueMap<String, ResponseCookie> getCookies() { return null; } } }

版本信息

<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.2.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-cloud.version>Finchley.SR2</spring-cloud.version> </properties>

理论部分参考: https://blog.51cto.com/thinklili/2329184

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI