springcloud gateway filter 重写response

发布时间 2023-04-28 14:42:13作者: 冬马党

 

import org.reactivestreams.Publisher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.factory.rewrite.CachedBodyOutputMessage;
import org.springframework.cloud.gateway.support.BodyInserterContext;
import org.springframework.context.MessageSource;
import org.springframework.context.NoSuchMessageException;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.context.i18n.SimpleLocaleContext;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ReactiveHttpOutputMessage;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserter;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.Locale;

import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR;

@Component
public class GlobalGatewayFilter implements GlobalFilter, Ordered {

    private final List<HttpMessageReader<?>> messageReaders;

    public GlobalGatewayFilter(ServerCodecConfigurer serverCodecConfigurer) {
        this.messageReaders = serverCodecConfigurer.getReaders();
    }

    @Autowired
    private MessageSource messageSource;


    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String language = request.getQueryParams().getFirst("lang");
        Locale locale = LocaleContextHolder.getLocale();
        if (language != null && language.length() > 0) {
            String[] split = language.split("_");
            locale = new Locale(split[0], split[1]);
        }
        LocaleContextHolder.setLocaleContext(new SimpleLocaleContext(locale), true);

            ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(exchange.getResponse()) {
                @Override
                public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
                    String originalResponseContentType = exchange.getAttribute(ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR);
                    if (originalResponseContentType.startsWith("application/json")){
                        ClientResponse clientResponse = ClientResponse
                                .create(this.getDelegate().getStatusCode(), messageReaders)
                                .body(Flux.from(body)).build();

                        Mono<String> bodyMono = clientResponse.bodyToMono(String.class).map((respBody) -> {
                            System.out.println(respBody);
                            Locale locale = LocaleContextHolder.getLocale();
                            try {
                                String s = messageSource.getMessage( "", null, locale);
                            }catch (NoSuchMessageException e){
                                e.printStackTrace();
                                return respBody;
                            }
                            return respBody;
                        });

                        BodyInserter<Mono<String>, ReactiveHttpOutputMessage> bodyInserter = BodyInserters.fromPublisher(bodyMono,
                                String.class);
                        CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(
                                exchange, exchange.getResponse().getHeaders());
                        return bodyInserter.insert(outputMessage, new BodyInserterContext())
                                .then(Mono.defer(() -> {
                                    Flux<DataBuffer> messageBody = outputMessage.getBody();
                                    HttpHeaders headers = getDelegate().getHeaders();
                                    if (!headers.containsKey(HttpHeaders.TRANSFER_ENCODING)) {
                                        messageBody = messageBody.doOnNext(data -> headers
                                                .setContentLength(data.readableByteCount()));
                                    }
                                    // TODO: fail if isStreamingMediaType?
                                    return getDelegate().writeWith(messageBody);
                                }));
                    }else {
                        return super.writeWith(body);
                    }

                }
            };
            return chain.filter(exchange.mutate().response(decoratedResponse).build());
    }


    @Override
    public int getOrder() {
        return -1;
    }

}