热门IT资讯网

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 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> 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 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

0