Spring Cloud Gateway — 修改RequestBody和Header

导读:本篇文章讲解 Spring Cloud Gateway — 修改RequestBody和Header,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

Spring Cloud Gateway — 修改RequestBody和Header

前言

目前项目有个需求,前端POST请求需要以xml形式传输,后端接口有些返回的是JSON格式有些返回的XML格式并且由于网络架构的需求,需要一个中间平台来处理这些请求。最终觉得利用Spring Cloud Gateway来实现。前端统POST请求统一用AJAX发送请求,中间平台将POST转换成XML形式,并且对相应的如果是xml形式的数据转成成JSON的格式进行返回。

读取和修改RequestBody

读取RequestBody的方法。
本人的一点猜测:这个方法可能是有缺陷的,因为在读取ResponseBody的时候由于后台的返回的数据量很大,好像是分了好几次发送,需要将其拼装在一起之后在做处理(后面的博客会讲到的)。故而猜测这里应该是同样的道理,不过由于请求参数不会很多,所有先不管后面有时间在进行测试。(后面确实发现有问题 —解决办法

    /**
     * 获取请求体中的字符串内容
     * @param serverHttpRequest
     * @return
     */
    private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest){
        //获取请求体
        Flux<DataBuffer> body = serverHttpRequest.getBody();
        StringBuilder sb = new StringBuilder();
        body.subscribe(buffer -> {
            byte[] bytes = new byte[buffer.readableByteCount()];
            buffer.read(bytes);
            DataBufferUtils.release(buffer);
            String bodyString = new String(bytes, StandardCharsets.UTF_8);
            sb.append(bodyString);
        });
        return sb.toString();
    }

对请求的方式进行判断,之后将数据转换成XML形式,并且需要重新传递。
重点

  1. 无论你修改了什么东西,都是需要new ServerHttpRequestDecorator 这个对象,并且调用你相对应的方法,例如我这边改了body就需要重写getBody这个方法。大家可以具体看看这个ServerHttpRequestDecorator的提供的方法就行了。
  2. 修改了Body 还需要修改CONTENT_LENGTH(下面会说的)
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest oldRequest= exchange.getRequest();
        URI uri = oldRequest.getURI();
        if("POST".equalsIgnoreCase(oldRequest.getMethodValue())) {
            Object requestBody = resolveBodyFromRequest(oldRequest);
            String xml = "";
            if(requestBody != null){
                xml = resolveBodyToXML(requestBody.toString());
            }
            //把request重新包装,继续传递
            ServerHttpRequest newRequest = null;
            try {
                byte[] bytes =  URLEncoder.encode(xml, "UTF-8").replaceAll("\\+", "%20").getBytes(StandardCharsets.UTF_8);
                DataBuffer bodyDataBuffer = stringBuffer(new String(bytes));
                Flux<DataBuffer> bodyFlux = Flux.just(bodyDataBuffer);
                newRequest = oldRequest.mutate().uri(uri).build();
                newRequest = new ServerHttpRequestDecorator(newRequest) {
                    @Override
                    public Flux<DataBuffer> getBody() {
                        return bodyFlux;
                    }
                };
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            return chain.filter(exchange.mutate().request(newRequest).build());
        }else{
            return chain.filter(exchange);
        }

    }

修改Header

和修改Body同理。修改CONTENT_TYPE和CONTENT_LENGTH
我是把同一个代码拆开了,为了看的清楚一些。大家把他们拼起来就好了

         // 定义新的消息头
                HttpHeaders headers = new HttpHeaders();
                headers.putAll(exchange.getRequest().getHeaders());
                // 由于修改了传递参数,需要重新设置CONTENT_LENGTH,长度是字节长度,不是字符串长度
                int length = bytes.length;
                headers.remove(HttpHeaders.CONTENT_LENGTH);
                headers.setContentLength(length);
                headers.set(HttpHeaders.CONTENT_TYPE, "text/xml");
				newRequest = new ServerHttpRequestDecorator(newRequest) {
                    @Override
                    public HttpHeaders getHeaders() {
                        return headers;
                    }
                };

添加路由

这个就比较平常了

@EnableAutoConfiguration
@Configuration
public class ApiLocator {

    @Autowired
    private RequestFilter requestFilter;

    @Bean
    public RouteLocator myRoutes(RouteLocatorBuilder builder) {
        List list = new ArrayList();
        list.add(requestFilter);

        RouteLocatorBuilder.Builder routes = builder.routes();
        RouteLocatorBuilder.Builder serviceProvider = routes
                .route("route3",
                        r -> r.path(SERVICE)
                                .filters(f -> {
                            f.filters(list);
                            return f;
                        }).uri(URI));
        RouteLocator routeLocator = serviceProvider.build();
        return routeLocator;
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/15321.html

(0)

相关推荐

半码博客——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!