istio 或 spring webflux 处理 header "Content-Encoding: deflate" 中是否有任何内置过滤器来解压缩请求 body
is there any built in filter in istio or in spring webflux handling header "Content-Encoding: deflate" to decompress the request body
我在 spring 云函数 webflux 上有一个微服务 运行,需要处理作为 http 请求发送的压缩数据 body
是否有任何 spring 内置的网络过滤器或配置来处理数据的解压缩
$ echo '{ "key":"hello" }' > body
$ curl -X POST -H "Content-Type: application/json" --data-binary @body http://localhost:8080 # prints 'hello'
$ echo '{ "key":"hello" }' | deflate > body.dat
$ curl -X POST -H "Content-Type: application/json" -H "Content-Encoding: deflate" --data-binary @body.dat http://localhost:8080 # fails
这可以在 istio envoy 过滤器中处理吗?
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.ServerWebExchangeDecorator;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.io.InputStream;
import java.util.List;
import java.util.zip.InflaterInputStream;
public class GzipFilter implements WebFilter {
private static final String ENCODING_VALUE = "deflate";
/**
* Process the Web request and (optionally) delegate to the next
* {@code WebFilter} through the given {@link WebFilterChain}.
*
* @param exchange the current server exchange
* @param chain provides a way to delegate to the next filter
* @return {@code Mono<Void>} to indicate when request processing is complete
*/
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
List<String> strings = exchange.getRequest().getHeaders().get(HttpHeaders.CONTENT_ENCODING);
if (strings != null && strings.contains(ENCODING_VALUE)) {
return chain.filter(new GzippedInputStreamWrapper(exchange));
} else {
return chain.filter(exchange);
}
}
}
public final class GzippedInputStreamWrapper extends ServerWebExchangeDecorator {
private final ServerHttpRequestDecorator requestDecorator;
protected GzippedInputStreamWrapper(ServerWebExchange delegate) {
super(delegate);
this.requestDecorator = new GzipRequestDecorator(delegate.getRequest());
}
@Override
public ServerHttpRequest getRequest() {
return this.requestDecorator;
}
}
public class GzipRequestDecorator extends ServerHttpRequestDecorator {
private final DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
public GzipRequestDecorator(ServerHttpRequest delegate) {
super(delegate);
}
@Override
public Flux<DataBuffer> getBody() {
return super.getBody().flatMap(dataBuffer -> {
try {
final InputStream gzipInputStream = new InflaterInputStream(dataBuffer.asInputStream());
return DataBufferUtils.readInputStream(() -> gzipInputStream, this.dataBufferFactory, gzipInputStream.available());
} catch (Exception e) {
return Flux.error(e);
}
});
}
}
定义 webfilter GzipFilter 拦截指定 header 的每个请求和进程。
GzipRequestDecorator 进行 body 内容膨胀并将其发送到下游处理函数的转换
我在 spring 云函数 webflux 上有一个微服务 运行,需要处理作为 http 请求发送的压缩数据 body
是否有任何 spring 内置的网络过滤器或配置来处理数据的解压缩
$ echo '{ "key":"hello" }' > body
$ curl -X POST -H "Content-Type: application/json" --data-binary @body http://localhost:8080 # prints 'hello'
$ echo '{ "key":"hello" }' | deflate > body.dat
$ curl -X POST -H "Content-Type: application/json" -H "Content-Encoding: deflate" --data-binary @body.dat http://localhost:8080 # fails
这可以在 istio envoy 过滤器中处理吗?
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.ServerWebExchangeDecorator;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.io.InputStream;
import java.util.List;
import java.util.zip.InflaterInputStream;
public class GzipFilter implements WebFilter {
private static final String ENCODING_VALUE = "deflate";
/**
* Process the Web request and (optionally) delegate to the next
* {@code WebFilter} through the given {@link WebFilterChain}.
*
* @param exchange the current server exchange
* @param chain provides a way to delegate to the next filter
* @return {@code Mono<Void>} to indicate when request processing is complete
*/
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
List<String> strings = exchange.getRequest().getHeaders().get(HttpHeaders.CONTENT_ENCODING);
if (strings != null && strings.contains(ENCODING_VALUE)) {
return chain.filter(new GzippedInputStreamWrapper(exchange));
} else {
return chain.filter(exchange);
}
}
}
public final class GzippedInputStreamWrapper extends ServerWebExchangeDecorator {
private final ServerHttpRequestDecorator requestDecorator;
protected GzippedInputStreamWrapper(ServerWebExchange delegate) {
super(delegate);
this.requestDecorator = new GzipRequestDecorator(delegate.getRequest());
}
@Override
public ServerHttpRequest getRequest() {
return this.requestDecorator;
}
}
public class GzipRequestDecorator extends ServerHttpRequestDecorator {
private final DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
public GzipRequestDecorator(ServerHttpRequest delegate) {
super(delegate);
}
@Override
public Flux<DataBuffer> getBody() {
return super.getBody().flatMap(dataBuffer -> {
try {
final InputStream gzipInputStream = new InflaterInputStream(dataBuffer.asInputStream());
return DataBufferUtils.readInputStream(() -> gzipInputStream, this.dataBufferFactory, gzipInputStream.available());
} catch (Exception e) {
return Flux.error(e);
}
});
}
}
定义 webfilter GzipFilter 拦截指定 header 的每个请求和进程。 GzipRequestDecorator 进行 body 内容膨胀并将其发送到下游处理函数的转换