16
16
17
17
package org .springframework .cloud .gateway .server .mvc .filter ;
18
18
19
+ import java .time .Duration ;
19
20
import java .util .Set ;
20
21
import java .util .concurrent .ConcurrentHashMap ;
21
22
import java .util .concurrent .atomic .AtomicInteger ;
22
23
23
24
import org .apache .commons .logging .Log ;
24
25
import org .apache .commons .logging .LogFactory ;
26
+ import org .apache .hc .core5 .util .Timeout ;
25
27
import org .junit .jupiter .api .Test ;
26
28
29
+ import org .springframework .beans .factory .ObjectProvider ;
27
30
import org .springframework .beans .factory .annotation .Autowired ;
28
31
import org .springframework .boot .SpringBootConfiguration ;
29
32
import org .springframework .boot .autoconfigure .EnableAutoConfiguration ;
33
+ import org .springframework .boot .http .client .ClientHttpRequestFactoryBuilder ;
30
34
import org .springframework .boot .test .context .SpringBootTest ;
31
35
import org .springframework .boot .test .context .SpringBootTest .WebEnvironment ;
32
36
import org .springframework .boot .test .web .server .LocalServerPort ;
37
+ import org .springframework .cloud .gateway .server .mvc .config .GatewayMvcProperties ;
38
+ import org .springframework .cloud .gateway .server .mvc .handler .ProxyExchange ;
39
+ import org .springframework .cloud .gateway .server .mvc .handler .ProxyExchangeHandlerFunction ;
40
+ import org .springframework .cloud .gateway .server .mvc .handler .RestClientProxyExchange ;
33
41
import org .springframework .cloud .gateway .server .mvc .test .HttpbinTestcontainers ;
34
42
import org .springframework .cloud .gateway .server .mvc .test .LocalServerPortUriResolver ;
35
43
import org .springframework .cloud .gateway .server .mvc .test .TestLoadBalancerConfig ;
36
44
import org .springframework .cloud .gateway .server .mvc .test .client .TestRestClient ;
37
45
import org .springframework .cloud .loadbalancer .annotation .LoadBalancerClient ;
46
+ import org .springframework .context .ApplicationContext ;
38
47
import org .springframework .context .annotation .Bean ;
48
+ import org .springframework .context .event .ContextRefreshedEvent ;
39
49
import org .springframework .core .log .LogMessage ;
40
50
import org .springframework .http .HttpMethod ;
41
51
import org .springframework .http .HttpStatus ;
42
52
import org .springframework .http .ResponseEntity ;
53
+ import org .springframework .http .client .ClientHttpRequestFactory ;
43
54
import org .springframework .test .context .ContextConfiguration ;
44
55
import org .springframework .util .StringUtils ;
45
56
import org .springframework .web .bind .annotation .GetMapping ;
46
57
import org .springframework .web .bind .annotation .PostMapping ;
47
58
import org .springframework .web .bind .annotation .RequestBody ;
48
59
import org .springframework .web .bind .annotation .RequestParam ;
49
60
import org .springframework .web .bind .annotation .RestController ;
61
+ import org .springframework .web .client .RestClient ;
62
+ import org .springframework .web .servlet .function .HandlerFunction ;
50
63
import org .springframework .web .servlet .function .RouterFunction ;
51
64
import org .springframework .web .servlet .function .ServerResponse ;
52
65
53
66
import static org .springframework .cloud .gateway .server .mvc .filter .FilterFunctions .adaptCachedBody ;
54
67
import static org .springframework .cloud .gateway .server .mvc .filter .FilterFunctions .prefixPath ;
68
+ import static org .springframework .cloud .gateway .server .mvc .filter .FilterFunctions .setPath ;
55
69
import static org .springframework .cloud .gateway .server .mvc .filter .RetryFilterFunctions .retry ;
56
70
import static org .springframework .cloud .gateway .server .mvc .handler .GatewayRouterFunctions .route ;
57
71
import static org .springframework .cloud .gateway .server .mvc .handler .HandlerFunctions .http ;
@@ -93,6 +107,17 @@ public void retryBodyWorks() {
93
107
.isEqualTo ("3" );
94
108
}
95
109
110
+ @ Test
111
+ public void retryWorksWithHttpComponentsClient () {
112
+ restClient .get ()
113
+ .uri ("/retrywithhttpcomponentsclient?key=retryWorksWithHttpComponentsClient" )
114
+ .exchange ()
115
+ .expectStatus ()
116
+ .isOk ()
117
+ .expectBody (String .class )
118
+ .isEqualTo ("3" );
119
+ }
120
+
96
121
@ SpringBootConfiguration
97
122
@ EnableAutoConfiguration
98
123
@ LoadBalancerClient (name = "httpbin" , configuration = TestLoadBalancerConfig .Httpbin .class )
@@ -110,6 +135,41 @@ public RouterFunction<ServerResponse> gatewayRouterFunctionsRetry() {
110
135
// @formatter:on
111
136
}
112
137
138
+ @ Bean
139
+ public RouterFunction <ServerResponse > gatewayRouterFunctionsRetryWithHttpComponentsClient (
140
+ GatewayMvcProperties properties ,
141
+ ObjectProvider <HttpHeadersFilter .RequestHttpHeadersFilter > requestHttpHeadersFilters ,
142
+ ObjectProvider <HttpHeadersFilter .ResponseHttpHeadersFilter > responseHttpHeadersFilters ,
143
+ ApplicationContext applicationContext ) {
144
+
145
+ // build httpComponents client factory
146
+ ClientHttpRequestFactory clientHttpRequestFactory = ClientHttpRequestFactoryBuilder .httpComponents ()
147
+ .withConnectionManagerCustomizer (builder -> builder .setMaxConnTotal (2 ).setMaxConnPerRoute (2 ))
148
+ .withDefaultRequestConfigCustomizer (
149
+ c -> c .setConnectionRequestTimeout (Timeout .of (Duration .ofMillis (3000 ))))
150
+ .build ();
151
+
152
+ // build proxyExchange use httpComponents
153
+ RestClient .Builder restClientBuilder = RestClient .builder ();
154
+ restClientBuilder .requestFactory (clientHttpRequestFactory );
155
+ ProxyExchange proxyExchange = new RestClientProxyExchange (restClientBuilder .build (), properties );
156
+
157
+ // build handler function use httpComponents
158
+ ProxyExchangeHandlerFunction function = new ProxyExchangeHandlerFunction (proxyExchange ,
159
+ requestHttpHeadersFilters , responseHttpHeadersFilters );
160
+ function .onApplicationEvent (new ContextRefreshedEvent (applicationContext ));
161
+
162
+ // @formatter:off
163
+ return route ("testretrywithhttpcomponentsclient" )
164
+ .GET ("/retrywithhttpcomponentsclient" , function )
165
+ .before (new LocalServerPortUriResolver ())
166
+ .filter (retry (3 ))
167
+ .filter (setPath ("/retry" ))
168
+ .filter (prefixPath ("/do" ))
169
+ .build ();
170
+ // @formatter:on
171
+ }
172
+
113
173
@ Bean
114
174
public RouterFunction <ServerResponse > gatewayRouterFunctionsRetryBody () {
115
175
// @formatter:off
0 commit comments