I want ot use Spring gateway proxy HTML webpage And replace some text,
Config like:
spring:
cloud:
gateway:
routes:
- id: replace_route
uri: http://my-web-site-article/
predicates:
- Path=/article/**
filters:
- ReplaceText
In my filter , I want to judge the 'origin response content-type', And modify if the Content-Type is html text. But I found the Content-Type is alway null . In zuul gateway I can use RequestContext.getCurrentContext().getOriginResponseHeaders(); Is there something similar in Spring Cloud Gateway ? Could you provide sample code for reference ? Many thanks! This question has puzzled me for a long time.
my code :
@Component
@Slf4j
public class ModifyGatewayFilterFactory extends ModifyRequestBodyGatewayFilterFactory {
HttpHeaders headers = exchange.getResponse().getHeaders();
List<String> strings = headers.get("Content-Type");
// [Content-Type alway null why ?]
// boolean html = strings.contains("text/html")
//TODO: if html (not pic,binaryFile) , Then modify and replace some text
}
In Zuul gateway code is :
@Override
public boolean shouldFilter() {
boolean isHtml = RequestContext.getCurrentContext().getOriginResponseHeaders().getContentType()..;
return isHtml;
}
@Override
public Object run() {
RequestContext context = getCurrentContext();
InputStream stream = context.getResponseDataStream();
if (stream == null) {
log.info("stream==null !!!");
return null;
}
// decompression
stream = context.getResponseGZipped() ? new GZIPInputStream(stream) : stream;
String body = StreamUtils.copyToString(stream, StandardCharsets.UTF_8);
// modify HTML Content
HttpServletRequest request = context.getRequest();
body = modifyBody2(request, body);
// compress gzip
ByteArrayOutputStream bos = new ByteArrayOutputStream(body.length());
GZIPOutputStream gzip = new GZIPOutputStream(bos);
gzip.write(body.getBytes(StandardCharsets.UTF_8));
gzip.close();
byte[] compressed = bos.toByteArray();
bos.close();
context.setResponseDataStream(new ByteArrayInputStream(compressed));
return null;
}
I finally found a solution,This code is work for me.
The point is to get parameters in getRewriteFunction. This is easy to do by extends ModifyResponseBodyGatewayFilterFactory
/**
* ref:<a href="https://juejin.cn/post/6933172840938078215">ref</a>
*
* @author donald
* @date 2021/02/24
*/
@Slf4j
@Component
public class CustomerModifyResponseGatewayFilterFactory extends ModifyResponseBodyGatewayFilterFactory {
@Override
public GatewayFilter apply(Config config) {
return new ModifyResponseGatewayFilter(this.getConfig());
}
private Config getConfig() {
Config config = new Config();
config.setRewriteFunction(byte[].class, byte[].class, getRewriteFunction());
return config;
}
private RewriteFunction<byte[], byte[]> getRewriteFunction() {
return (exchange, resp) -> {
ServerHttpResponse response = exchange.getResponse();
String contentType = response.getHeaders().getFirst("Content-Type");
//todo:gzip,
if (contentType !=null &&contentType.contains(MediaType.TEXT_HTML_VALUE)){
String html = "modify-html";
return Mono.just(html.getBytes(StandardCharsets.UTF_8));
}else {
return Mono.just(resp);
}
};
}
}