1616
1717package org .springframework .http .client .reactive ;
1818
19+ import java .util .Objects ;
1920import java .util .concurrent .atomic .AtomicBoolean ;
2021
22+ import org .reactivestreams .Publisher ;
23+ import org .reactivestreams .Subscriber ;
24+ import org .reactivestreams .Subscription ;
2125import reactor .core .publisher .Flux ;
2226
2327import org .springframework .core .io .buffer .DataBuffer ;
@@ -55,16 +59,7 @@ protected AbstractClientHttpResponse(HttpStatusCode statusCode, HttpHeaders head
5559 this .statusCode = statusCode ;
5660 this .headers = headers ;
5761 this .cookies = cookies ;
58- this .body = singleSubscription (body );
59- }
60-
61- private static Flux <DataBuffer > singleSubscription (Flux <DataBuffer > body ) {
62- AtomicBoolean subscribed = new AtomicBoolean ();
63- return body .doOnSubscribe (s -> {
64- if (!subscribed .compareAndSet (false , true )) {
65- throw new IllegalStateException ("The client response body can only be consumed once" );
66- }
67- });
62+ this .body = Flux .from (new SingleSubscriberPublisher <>(body ));
6863 }
6964
7065
@@ -87,4 +82,39 @@ public MultiValueMap<String, ResponseCookie> getCookies() {
8782 public Flux <DataBuffer > getBody () {
8883 return this .body ;
8984 }
85+
86+
87+ private static final class SingleSubscriberPublisher <T > implements Publisher <T > {
88+
89+ private static final Subscription NO_OP_SUBSCRIPTION = new Subscription () {
90+ @ Override
91+ public void request (long l ) {
92+ }
93+
94+ @ Override
95+ public void cancel () {
96+ }
97+ };
98+
99+ private final Publisher <T > delegate ;
100+
101+ private final AtomicBoolean subscribed = new AtomicBoolean ();
102+
103+
104+ public SingleSubscriberPublisher (Publisher <T > delegate ) {
105+ this .delegate = delegate ;
106+ }
107+
108+ @ Override
109+ public void subscribe (Subscriber <? super T > subscriber ) {
110+ Objects .requireNonNull (subscriber , "Subscriber must not be null" );
111+ if (this .subscribed .compareAndSet (false , true )) {
112+ this .delegate .subscribe (subscriber );
113+ }
114+ else {
115+ subscriber .onSubscribe (NO_OP_SUBSCRIPTION );
116+ subscriber .onError (new IllegalStateException ("The client response body can only be consumed once" ));
117+ }
118+ }
119+ }
90120}
0 commit comments