私はSpring5、Netty、Springwebfluxを使用してAPIGatewayを開発しています。リクエストをゲートウェイで停止したい場合もありますが、リクエストの本文を読み取ってログに記録し、クライアントにエラーを返したい場合もあります。
私は本文にサブスクライブすることにより、WebFilterでこれを実行しようとしています。
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
if (enabled) {
logger.debug("gateway is enabled. The Request is routed.");
return chain.filter(exchange);
} else {
logger.debug("gateway is disabled. A 404 error is returned.");
exchange.getRequest().getBody().subscribe();
exchange.getResponse().setStatusCode(HttpStatus.NOT_FOUND);
return exchange.getResponse().writeWith(Mono.just(exchange.getResponse().bufferFactory().allocateBuffer(0)));
}
}
私がこれをするとき、それは体の内容が小さいときに働きます。しかし、私が大きなボビーを持っているとき、フラックスの最初の要素だけが読み取られるので、私は全身を持つことができません。これを行う方法はありますか?
ここでの問題は、フィルター内で手動でサブスクライブしていることです。つまり、パイプラインの残りの部分から要求の読み取りを切断しています。 subscribe()
を呼び出すと、基になるDisposable
の管理に役立つSubscription
が得られます。
したがって、次のように、プロセス全体を単一のパイプラインとして接続する必要があります。
Flux<DataBuffer> requestBody = exchange.getRequest().getBody();
// decode the request body as a Mono or a Flux
Mono<String> decodedBody = decodeBody(requestBody);
exchange.getResponse().setStatusCode(HttpStatus.NOT_FOUND);
return decodedBody.doOnNext(s -> logger.info(s))
.then(exchange.getResponse().setComplete());
リクエスト本文全体をMono
としてデコードすると、ゲートウェイはリクエスト本文全体をメモリにバッファリングする必要があることに注意してください。
DataBuffer
は、意図的に低レベルのタイプです。それを文字列としてデコードする(つまり、サンプルのdecodeBody
methodを実装する)場合は、Decoder
のようなSpringのさまざまなStringDecoder
実装の1つを使用できます。
これはかなり大きくて複雑なスペースであるため、 Spring Cloud Gateway を使用したり、確認したりできます。これは、まさにそれ以上のことを行います。
1.投稿ルートに "readBody()"を追加します。
builder.routes()
.route("get_route", r -> r.path("/**")
.and().method("GET")
.filters(f -> f.filter(myFilter))
.uri(myUrl))
.route("post_route", r -> r.path("/**")
.and().method("POST")
.and().readBody(String.class, requestBody -> {return true;})
.filters(f -> f.filter(myFilter))
.uri(myUrl))
2.次に、フィルターで本文の文字列を取得できます。
String body = exchange.getAttribute("cachedRequestBodyObject");
利点:
ブロッキングなし。
さらなるプロセスのために体を補充する必要はありません。
Spring Boot 2.0.6.RELEASE + Sring Cloud Finchley.SR2 + Spring CloudGatewayで動作します。