Skip to content

Commit 9f06514

Browse files
kstrijbosphilwebb
authored andcommitted
Make it easier to set bufferRequestBody
Update `RestTemplateBuilder` to make it easier to set the `bufferRequestBody` value on a underlying `ClientHttpRequestFactory` See gh-16972
1 parent 750d251 commit 9f06514

File tree

2 files changed

+136
-4
lines changed

2 files changed

+136
-4
lines changed

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/RestTemplateBuilder.java

Lines changed: 72 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
* @author Andy Wilkinson
6161
* @author Brian Clozel
6262
* @author Dmytro Nosan
63+
* @author Kevin Strijbos
6364
* @since 1.4.0
6465
*/
6566
public class RestTemplateBuilder {
@@ -506,6 +507,22 @@ public RestTemplateBuilder setReadTimeout(Duration readTimeout) {
506507
this.interceptors);
507508
}
508509

510+
/**
511+
* Sets the bufferrequestbody value on the underlying
512+
* {@link ClientHttpRequestFactory}.
513+
* @param bufferRequestBody value of the bufferRequestBody parameter
514+
* @return a new builder instance.
515+
* @since 2.1.0
516+
*/
517+
public RestTemplateBuilder setBufferRequestBody(boolean bufferRequestBody) {
518+
return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri,
519+
this.messageConverters, this.requestFactorySupplier,
520+
this.uriTemplateHandler, this.errorHandler, this.basicAuthentication,
521+
this.restTemplateCustomizers,
522+
this.requestFactoryCustomizer.bufferRequestBody(bufferRequestBody),
523+
this.interceptors);
524+
}
525+
509526
/**
510527
* Build a new {@link RestTemplate} instance and configure it using this builder.
511528
* @return a configured {@link RestTemplate} instance.
@@ -617,21 +634,35 @@ private static class RequestFactoryCustomizer
617634

618635
private final Duration readTimeout;
619636

637+
private final boolean bufferRequestBody;
638+
639+
private final boolean bufferRequestBodyFlag;
640+
620641
RequestFactoryCustomizer() {
621-
this(null, null);
642+
this(null, null, true, false);
622643
}
623644

624-
private RequestFactoryCustomizer(Duration connectTimeout, Duration readTimeout) {
645+
private RequestFactoryCustomizer(Duration connectTimeout, Duration readTimeout,
646+
boolean bufferRequestBody, boolean bufferRequestBodyFlag) {
625647
this.connectTimeout = connectTimeout;
626648
this.readTimeout = readTimeout;
649+
this.bufferRequestBody = bufferRequestBody;
650+
this.bufferRequestBodyFlag = bufferRequestBodyFlag;
627651
}
628652

629653
public RequestFactoryCustomizer connectTimeout(Duration connectTimeout) {
630-
return new RequestFactoryCustomizer(connectTimeout, this.readTimeout);
654+
return new RequestFactoryCustomizer(connectTimeout, this.readTimeout,
655+
this.bufferRequestBody, this.bufferRequestBodyFlag);
631656
}
632657

633658
public RequestFactoryCustomizer readTimeout(Duration readTimeout) {
634-
return new RequestFactoryCustomizer(this.connectTimeout, readTimeout);
659+
return new RequestFactoryCustomizer(this.connectTimeout, readTimeout,
660+
this.bufferRequestBody, this.bufferRequestBodyFlag);
661+
}
662+
663+
public RequestFactoryCustomizer bufferRequestBody(boolean bufferRequestBody) {
664+
return new RequestFactoryCustomizer(this.connectTimeout, this.readTimeout,
665+
bufferRequestBody, true);
635666
}
636667

637668
@Override
@@ -646,6 +677,10 @@ public void accept(ClientHttpRequestFactory requestFactory) {
646677
new TimeoutRequestFactoryCustomizer(this.readTimeout, "setReadTimeout")
647678
.customize(unwrappedRequestFactory);
648679
}
680+
if (this.bufferRequestBodyFlag) {
681+
new BufferRequestBodyFactoryCustomizer(this.bufferRequestBody,
682+
"setBufferRequestBody").customize(unwrappedRequestFactory);
683+
}
649684
}
650685

651686
private ClientHttpRequestFactory unwrapRequestFactoryIfNecessary(
@@ -695,6 +730,39 @@ private Method findMethod(ClientHttpRequestFactory factory) {
695730

696731
}
697732

733+
/**
734+
* {@link ClientHttpRequestFactory} customizer to call a "set buffer request body"
735+
* method.
736+
*/
737+
private static final class BufferRequestBodyFactoryCustomizer {
738+
739+
private final boolean bufferRequestBody;
740+
741+
private final String methodName;
742+
743+
BufferRequestBodyFactoryCustomizer(boolean bufferRequestBody,
744+
String methodName) {
745+
this.bufferRequestBody = bufferRequestBody;
746+
this.methodName = methodName;
747+
}
748+
749+
void customize(ClientHttpRequestFactory factory) {
750+
ReflectionUtils.invokeMethod(findMethod(factory), factory,
751+
this.bufferRequestBody);
752+
}
753+
754+
private Method findMethod(ClientHttpRequestFactory factory) {
755+
Method method = ReflectionUtils.findMethod(factory.getClass(),
756+
this.methodName, boolean.class);
757+
if (method != null) {
758+
return method;
759+
}
760+
throw new IllegalStateException("Request factory " + factory.getClass()
761+
+ " does not have a " + this.methodName + "(boolean) method");
762+
}
763+
764+
}
765+
698766
}
699767

700768
}

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/RestTemplateBuilderTests.java

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747

4848
import static org.assertj.core.api.Assertions.assertThat;
4949
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
50+
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
5051
import static org.mockito.ArgumentMatchers.any;
5152
import static org.mockito.Mockito.inOrder;
5253
import static org.mockito.Mockito.mock;
@@ -63,6 +64,7 @@
6364
* @author Phillip Webb
6465
* @author Andy Wilkinson
6566
* @author Dmytro Nosan
67+
* @author Kevin Strijbos
6668
*/
6769
public class RestTemplateBuilderTests {
6870

@@ -480,6 +482,23 @@ public void readTimeoutCanBeConfiguredOnHttpComponentsRequestFactory() {
480482
"requestConfig")).getSocketTimeout()).isEqualTo(1234);
481483
}
482484

485+
@Test
486+
public void bufferRequestBodyCanBeConfiguredOnHttpComponentsRequestFactory() {
487+
ClientHttpRequestFactory requestFactory = this.builder
488+
.requestFactory(HttpComponentsClientHttpRequestFactory.class)
489+
.setBufferRequestBody(false).build().getRequestFactory();
490+
assertThat(requestFactory).hasFieldOrPropertyWithValue("bufferRequestBody",
491+
false);
492+
requestFactory = this.builder
493+
.requestFactory(HttpComponentsClientHttpRequestFactory.class)
494+
.setBufferRequestBody(true).build().getRequestFactory();
495+
assertThat(requestFactory).hasFieldOrPropertyWithValue("bufferRequestBody", true);
496+
requestFactory = this.builder
497+
.requestFactory(HttpComponentsClientHttpRequestFactory.class).build()
498+
.getRequestFactory();
499+
assertThat(requestFactory).hasFieldOrPropertyWithValue("bufferRequestBody", true);
500+
}
501+
483502
@Test
484503
public void connectTimeoutCanBeConfiguredOnSimpleRequestFactory() {
485504
ClientHttpRequestFactory requestFactory = this.builder
@@ -496,6 +515,21 @@ public void readTimeoutCanBeConfiguredOnSimpleRequestFactory() {
496515
assertThat(requestFactory).hasFieldOrPropertyWithValue("readTimeout", 1234);
497516
}
498517

518+
@Test
519+
public void bufferRequestBodyCanBeConfiguredOnSimpleRequestFactory() {
520+
ClientHttpRequestFactory requestFactory = this.builder
521+
.requestFactory(SimpleClientHttpRequestFactory.class)
522+
.setBufferRequestBody(false).build().getRequestFactory();
523+
assertThat(requestFactory).hasFieldOrPropertyWithValue("bufferRequestBody",
524+
false);
525+
requestFactory = this.builder.requestFactory(SimpleClientHttpRequestFactory.class)
526+
.setBufferRequestBody(true).build().getRequestFactory();
527+
assertThat(requestFactory).hasFieldOrPropertyWithValue("bufferRequestBody", true);
528+
requestFactory = this.builder.requestFactory(SimpleClientHttpRequestFactory.class)
529+
.build().getRequestFactory();
530+
assertThat(requestFactory).hasFieldOrPropertyWithValue("bufferRequestBody", true);
531+
}
532+
499533
@Test
500534
public void connectTimeoutCanBeConfiguredOnOkHttp3RequestFactory() {
501535
ClientHttpRequestFactory requestFactory = this.builder
@@ -516,6 +550,15 @@ public void readTimeoutCanBeConfiguredOnOkHttp3RequestFactory() {
516550
.isEqualTo(1234);
517551
}
518552

553+
@Test
554+
public void bufferRequestBodyCanNotBeConfiguredOnOkHttp3RequestFactory() {
555+
assertThatIllegalStateException()
556+
.isThrownBy(() -> this.builder
557+
.requestFactory(OkHttp3ClientHttpRequestFactory.class)
558+
.setBufferRequestBody(false).build().getRequestFactory())
559+
.withMessageContaining(OkHttp3ClientHttpRequestFactory.class.getName());
560+
}
561+
519562
@Test
520563
public void connectTimeoutCanBeConfiguredOnAWrappedRequestFactory() {
521564
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
@@ -536,6 +579,27 @@ public void readTimeoutCanBeConfiguredOnAWrappedRequestFactory() {
536579
assertThat(requestFactory).hasFieldOrPropertyWithValue("readTimeout", 1234);
537580
}
538581

582+
@Test
583+
public void bufferRequestBodyCanBeConfiguredOnAWrappedRequestFactory() {
584+
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
585+
this.builder
586+
.requestFactory(
587+
() -> new BufferingClientHttpRequestFactory(requestFactory))
588+
.setBufferRequestBody(false).build();
589+
assertThat(requestFactory).hasFieldOrPropertyWithValue("bufferRequestBody",
590+
false);
591+
this.builder
592+
.requestFactory(
593+
() -> new BufferingClientHttpRequestFactory(requestFactory))
594+
.setBufferRequestBody(true).build();
595+
assertThat(requestFactory).hasFieldOrPropertyWithValue("bufferRequestBody", true);
596+
this.builder
597+
.requestFactory(
598+
() -> new BufferingClientHttpRequestFactory(requestFactory))
599+
.build();
600+
assertThat(requestFactory).hasFieldOrPropertyWithValue("bufferRequestBody", true);
601+
}
602+
539603
@Test
540604
public void unwrappingDoesNotAffectRequestFactoryThatIsSetOnTheBuiltTemplate() {
541605
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();

0 commit comments

Comments
 (0)