Spirng gateway 拦截 response并修改然后返回给客户端

BodyHandlerFunction.java
import org.reactivestreams.Publisher;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpResponse;
import reactor.core.publisher.Mono;
import java.util.function.BiFunction;

public interface BodyHandlerFunction extends
        BiFunction, Mono> {
}
BodyHandlerServerHttpResponseDecorator.java
import org.reactivestreams.Publisher;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

public class BodyHandlerServerHttpResponseDecorator
        extends ServerHttpResponseDecorator {

    /**
     * body 处理拦截器
     */
    private BodyHandlerFunction bodyHandler = initDefaultBodyHandler();

    /**
     * 构造函数
     *
     * @param bodyHandler
     * @param delegate
     */
    public BodyHandlerServerHttpResponseDecorator(
            BodyHandlerFunction bodyHandler, ServerHttpResponse delegate) {
        super(delegate);
        if (bodyHandler != null) {
            this.bodyHandler = bodyHandler;
        }
    }

    @Override
    public Mono writeWith(Publisher body) {
        //body 拦截处理器处理响应
        return bodyHandler.apply(getDelegate(), body);
    }

    @Override
    public Mono writeAndFlushWith(
            Publisher> body) {
        return writeWith(Flux.from(body).flatMapSequential(p -> p));
    }

    /**
     * 默认body拦截处理器
     *
     * @return
     */
    private BodyHandlerFunction initDefaultBodyHandler() {
        return (resp, body) -> resp.writeWith(body);
    }
}
ResponseGlobalFilter.java
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.NettyWriteResponseFilter;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.web.server.ServerWebExchange;
import org.synchronoss.cloud.nio.multipart.util.IOUtils;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.io.IOException;

@Configuration
public class ResponseGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono filter(ServerWebExchange exchange,
                             GatewayFilterChain chain) {
        //如果是获取验证码的请求,则跳出
        if(exchange.getRequest().getPath().value().contains("captcha")){
            return chain.filter(exchange);
        }
        //构建响应拦截处理器
        BodyHandlerFunction bodyHandler = (resp, body) -> Flux.from(body)
                .map(dataBuffer -> {
                    //响应信息转换为字符串
                    String reqBody = null;
                    try {
                        //dataBuffer 转换为String
                        reqBody = IOUtils
                                .inputStreamAsString(dataBuffer.asInputStream(), "UTF-8")
                                .replaceAll(">\\s{1,}<", "><");
                        System.out.println(reqBody);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    return reqBody;
                })
                .flatMap(orgBody -> {
                    //根据原有的响应信息构建新响应信息并写入到resp中
                    //此处可以根据业务进行组装新的响应信息,
                    // 例如:登录后创建会话
                    //- 拿到登录请求的响应信息,判断登录是否成功
                    //- 登录成功调用创建会话接口,根据创建会话接口返回组装登录的真实响应
                    String rbody = orgBody + "";
                    HttpHeaders headers = resp.getHeaders();
                    if(headers.get("Access-Control-Allow-Origin")!=null && headers.get("Access-Control-Allow-Origin").size()>1){
                        String value=headers.get("Access-Control-Allow-Origin").get(0);
                        headers.remove("Access-Control-Allow-Origin");
                        headers.setAccessControlAllowOrigin(value);
                    }
                    if(headers.get("Access-Control-Allow-Credentials")!=null && headers.get("Access-Control-Allow-Credentials").size()>1){
                        String value=headers.get("Access-Control-Allow-Credentials").get(0);
                        headers.remove("Access-Control-Allow-Credentials");
                        headers.setAccessControlAllowCredentials(value=="true");
                    }
                    return resp.writeWith(Flux.just(rbody)
                            .map(bx -> resp.bufferFactory()
                                    .wrap(bx.getBytes())));
                }).then();

        //构建响应包装类
        BodyHandlerServerHttpResponseDecorator responseDecorator = new BodyHandlerServerHttpResponseDecorator(
                bodyHandler, exchange.getResponse());
        return chain
                .filter(exchange.mutate().response(responseDecorator).build());
    }

    @Override
    public int getOrder() {
        //WRITE_RESPONSE_FILTER 之前执行
        return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER - 1;
    }

}

 

你可能感兴趣的:(Spirng gateway 拦截 response并修改然后返回给客户端)