From 9fc302ec724576b5e3016a7b6684746160a1ef13 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Tue, 23 Jul 2019 13:31:41 -0400 Subject: [PATCH] Adds support for netty wiretap on server and client. fixes gh-1194 --- .../main/asciidoc/spring-cloud-gateway.adoc | 25 ++++++++++++++++++- .../config/GatewayAutoConfiguration.java | 21 ++++++++++++++-- .../gateway/config/HttpClientProperties.java | 24 +++++++++++++++--- ...itional-spring-configuration-metadata.json | 6 +++++ 4 files changed, 70 insertions(+), 6 deletions(-) diff --git a/docs/src/main/asciidoc/spring-cloud-gateway.adoc b/docs/src/main/asciidoc/spring-cloud-gateway.adoc index 4099a2c1..32ee1e37 100644 --- a/docs/src/main/asciidoc/spring-cloud-gateway.adoc +++ b/docs/src/main/asciidoc/spring-cloud-gateway.adoc @@ -21,7 +21,7 @@ for details on setting up your build system with the current Spring Cloud Releas If you include the starter, but, for some reason, you do not want the gateway to be enabled, set `spring.cloud.gateway.enabled=false`. -IMPORTANT: Spring Cloud Gateway is built upon https://spring.io/projects/spring-boot#learn[Spring Boot 2.0], +IMPORTANT: Spring Cloud Gateway is built upon https://spring.io/projects/spring-boot#learn[Spring Boot 2.x], https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html[Spring WebFlux], and https://projectreactor.io/docs[Project Reactor]. As a consequence many of the familiar synchronous libraries (Spring Data and Spring Security, for example) and patterns you may @@ -1704,6 +1704,29 @@ The table below summarises the Spring Cloud Gateway actuator endpoints. Note tha |=== +[[troubleshooting]] +== Troubleshooting + +=== Log Levels + +Below are some useful loggers that contain valuable trouble shooting infomration at the `DEBUG` and `TRACE` levels. + +- `org.springframework.cloud.gateway` +- `org.springframework.http.server.reactive` +- `org.springframework.web.reactive` +- `org.springframework.boot.autoconfigure.web` +- `reactor.netty` +- `redisratelimiter` + +=== Wiretap + +The Reactor Netty `HttpClient` and `HttpServer` can have wiretap enabled. When combined +with setting the `reactor.netty` log level to `DEBUG` or `TRACE` will enable logging of +information such as headers and bodies sent and received across the wire. To enable this, +set `spring.cloud.gateway.httpserver.wiretap=true` and/or +`spring.cloud.gateway.httpclient.wiretap=true` for the `HttpServer` and `HttpClient` +respectively. + == Developer Guide TODO: overview of writing custom integrations diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java index a22ac5c5..663294cc 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java @@ -40,10 +40,13 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.NoneNestedConditions; +import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.autoconfigure.web.embedded.NettyWebServerFactoryCustomizer; import org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration; import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.PropertyMapper; +import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; import org.springframework.cloud.gateway.actuate.GatewayControllerEndpoint; import org.springframework.cloud.gateway.actuate.GatewayLegacyControllerEndpoint; import org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter; @@ -517,6 +520,19 @@ public class GatewayAutoConfiguration { @ConditionalOnClass(HttpClient.class) protected static class NettyConfiguration { + @Bean + @ConditionalOnProperty(name = "spring.cloud.gateway.httpserver.wiretap") + public NettyWebServerFactoryCustomizer nettyServerWiretapCustomizer( + Environment environment, ServerProperties serverProperties) { + return new NettyWebServerFactoryCustomizer(environment, serverProperties) { + @Override + public void customize(NettyReactiveWebServerFactory factory) { + factory.addServerCustomizers(httpServer -> httpServer.wiretap(true)); + super.customize(factory); + } + }; + } + @Bean @ConditionalOnMissingBean public HttpClient gatewayHttpClient(HttpClientProperties properties) { @@ -594,8 +610,9 @@ public class GatewayAutoConfiguration { }); } - // TODO: add configuration to turn on wiretap - // httpClient = httpClient.wiretap(true); + if (properties.isWiretap()) { + httpClient = httpClient.wiretap(true); + } return httpClient; } diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/HttpClientProperties.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/HttpClientProperties.java index a2121f0e..e37f9865 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/HttpClientProperties.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/HttpClientProperties.java @@ -57,6 +57,9 @@ public class HttpClientProperties { /** SSL configuration for Netty HttpClient. */ private Ssl ssl = new Ssl(); + /** Enables wiretap debugging for Netty HttpClient. */ + private boolean wiretap; + public Integer getConnectTimeout() { return connectTimeout; } @@ -97,11 +100,26 @@ public class HttpClientProperties { this.ssl = ssl; } + public boolean isWiretap() { + return this.wiretap; + } + + public void setWiretap(boolean wiretap) { + this.wiretap = wiretap; + } + @Override public String toString() { - return new ToStringCreator(this).append("connectTimeout", connectTimeout) - .append("responseTimeout", responseTimeout).append("pool", pool) - .append("proxy", proxy).append("ssl", ssl).toString(); + // @formatter:off + return new ToStringCreator(this) + .append("connectTimeout", connectTimeout) + .append("responseTimeout", responseTimeout) + .append("pool", pool) + .append("proxy", proxy) + .append("ssl", ssl) + .append("wiretap", wiretap) + .toString(); + // @formatter:on } public static class Pool { diff --git a/spring-cloud-gateway-core/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-gateway-core/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 0cd1a91b..94badd07 100644 --- a/spring-cloud-gateway-core/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-cloud-gateway-core/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -17,6 +17,12 @@ "type": "java.lang.Boolean", "description": "Enables the collection of metrics data.", "defaultValue": "true" + }, + { + "name": "spring.cloud.gateway.httpserver.wiretap", + "type": "java.lang.Boolean", + "description": "Enables wiretap debugging for Netty HttpServer.", + "defaultValue": "false" } ] }