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