2323import java .util .Collections ;
2424import java .util .HashSet ;
2525import java .util .Locale ;
26+ import java .util .Objects ;
2627import java .util .Set ;
2728import java .util .function .Function ;
2829import java .util .stream .Collectors ;
2930
31+ import org .jspecify .annotations .Nullable ;
3032import org .reactivestreams .Publisher ;
3133import reactor .core .publisher .Mono ;
3234
@@ -121,19 +123,19 @@ public class ProxyExchange<T> {
121123
122124 private HttpMethod httpMethod ;
123125
124- private URI uri ;
126+ private @ Nullable URI uri ;
125127
126128 private WebClient rest ;
127129
128- private Publisher <Object > body ;
130+ private @ Nullable Publisher <Object > body ;
129131
130132 private boolean hasBody = false ;
131133
132134 private ServerWebExchange exchange ;
133135
134136 private BindingContext bindingContext ;
135137
136- private Set <String > excluded ;
138+ private @ Nullable Set <String > excluded ;
137139
138140 private HttpHeaders headers = new HttpHeaders ();
139141
@@ -244,6 +246,7 @@ public String path(String prefix) {
244246 }
245247
246248 public Mono <ResponseEntity <T >> get () {
249+ Objects .requireNonNull (uri , "URI must not be null" );
247250 RequestEntity <?> requestEntity = headers ((BodyBuilder ) RequestEntity .get (uri )).build ();
248251 return exchange (requestEntity );
249252 }
@@ -253,6 +256,7 @@ public <S> Mono<ResponseEntity<S>> get(Function<ResponseEntity<T>, ResponseEntit
253256 }
254257
255258 public Mono <ResponseEntity <T >> head () {
259+ Objects .requireNonNull (uri , "URI must not be null" );
256260 RequestEntity <?> requestEntity = headers ((BodyBuilder ) RequestEntity .head (uri )).build ();
257261 return exchange (requestEntity );
258262 }
@@ -262,6 +266,7 @@ public <S> Mono<ResponseEntity<S>> head(Function<ResponseEntity<T>, ResponseEnti
262266 }
263267
264268 public Mono <ResponseEntity <T >> options () {
269+ Objects .requireNonNull (uri , "URI must not be null" );
265270 RequestEntity <?> requestEntity = headers ((BodyBuilder ) RequestEntity .options (uri )).build ();
266271 return exchange (requestEntity );
267272 }
@@ -271,25 +276,30 @@ public <S> Mono<ResponseEntity<S>> options(Function<ResponseEntity<T>, ResponseE
271276 }
272277
273278 public Mono <ResponseEntity <T >> post () {
274- RequestEntity <Object > requestEntity = headers (RequestEntity .post (uri )).body (body ());
275- return exchange (requestEntity );
279+ return doExchange (RequestEntity ::post );
276280 }
277281
278282 public <S > Mono <ResponseEntity <S >> post (Function <ResponseEntity <T >, ResponseEntity <S >> converter ) {
279283 return post ().map (converter ::apply );
280284 }
281285
282286 public Mono <ResponseEntity <T >> delete () {
283- RequestEntity <Object > requestEntity = headers ((BodyBuilder ) RequestEntity .delete (uri )).body (body ());
284- return exchange (requestEntity );
287+ return doExchange (uri -> (BodyBuilder ) RequestEntity .delete (uri ));
285288 }
286289
287290 public <S > Mono <ResponseEntity <S >> delete (Function <ResponseEntity <T >, ResponseEntity <S >> converter ) {
288291 return delete ().map (converter ::apply );
289292 }
290293
291294 public Mono <ResponseEntity <T >> put () {
292- RequestEntity <Object > requestEntity = headers (RequestEntity .put (uri )).body (body ());
295+ return doExchange (RequestEntity ::put );
296+ }
297+
298+ private Mono <ResponseEntity <T >> doExchange (Function <URI , RequestEntity .BodyBuilder > getBodyBuilder ) {
299+ Objects .requireNonNull (uri , "URI must not be null" );
300+ BodyBuilder bodyBuilder = headers (getBodyBuilder .apply (uri ));
301+ Publisher <?> body = body ();
302+ RequestEntity <?> requestEntity = body != null ? bodyBuilder .body (body ) : bodyBuilder .build ();
293303 return exchange (requestEntity );
294304 }
295305
@@ -298,8 +308,7 @@ public <S> Mono<ResponseEntity<S>> put(Function<ResponseEntity<T>, ResponseEntit
298308 }
299309
300310 public Mono <ResponseEntity <T >> patch () {
301- RequestEntity <Object > requestEntity = headers (RequestEntity .patch (uri )).body (body ());
302- return exchange (requestEntity );
311+ return doExchange (RequestEntity ::patch );
303312 }
304313
305314 public <S > Mono <ResponseEntity <S >> patch (Function <ResponseEntity <T >, ResponseEntity <S >> converter ) {
@@ -360,6 +369,7 @@ else if (httpMethod.equals(HttpMethod.PATCH)) {
360369
361370 private Mono <ResponseEntity <T >> exchange (RequestEntity <?> requestEntity ) {
362371 Type type = this .responseType ;
372+ Objects .requireNonNull (requestEntity .getMethod (), "Method must not be null" );
363373 RequestBodySpec builder = rest .method (requestEntity .getMethod ())
364374 .uri (requestEntity .getUrl ())
365375 .headers (headers -> addHeaders (headers , requestEntity .getHeaders ()));
@@ -388,9 +398,12 @@ else if (requestEntity.getBody() != null) {
388398
389399 private void addHeaders (HttpHeaders headers , HttpHeaders toAdd ) {
390400 Set <String > filteredKeys = filterHeaderKeys (toAdd );
391- filteredKeys .stream ()
392- .filter (key -> !headers .containsHeader (key ))
393- .forEach (header -> headers .addAll (header , toAdd .get (header )));
401+ filteredKeys .stream ().filter (key -> !headers .containsHeader (key )).forEach (header -> {
402+ java .util .List <String > headerValues = toAdd .get (header );
403+ if (headerValues != null ) {
404+ headers .addAll (header , headerValues );
405+ }
406+ });
394407 }
395408
396409 private Set <String > filterHeaderKeys (HttpHeaders headers ) {
@@ -404,7 +417,10 @@ private Set<String> filterHeaderKeys(HttpHeaders headers) {
404417 private BodyBuilder headers (BodyBuilder builder ) {
405418 proxy ();
406419 for (String name : filterHeaderKeys (headers )) {
407- builder .header (name , headers .get (name ).toArray (new String [0 ]));
420+ java .util .List <String > headerValues = headers .get (name );
421+ if (headerValues != null ) {
422+ builder .header (name , headerValues .toArray (new String [0 ]));
423+ }
408424 }
409425 return builder ;
410426 }
@@ -443,7 +459,7 @@ private void appendForwarded(URI uri) {
443459 headers .set ("forwarded" , forwarded );
444460 }
445461
446- private String forwarded (URI uri , String hostHeader ) {
462+ private String forwarded (URI uri , @ Nullable String hostHeader ) {
447463 if (StringUtils .hasText (hostHeader )) {
448464 return "host=" + hostHeader ;
449465 }
@@ -453,7 +469,7 @@ private String forwarded(URI uri, String hostHeader) {
453469 return String .format ("host=%s;proto=%s" , uri .getHost (), uri .getScheme ());
454470 }
455471
456- private Publisher <?> body () {
472+ private @ Nullable Publisher <?> body () {
457473 Publisher <?> body = this .body ;
458474 if (body != null ) {
459475 return body ;
@@ -469,11 +485,14 @@ private Publisher<?> body() {
469485 * that it would have been for a <code>@RequestBody</code>.
470486 * @return the request body
471487 */
472- private Mono <Object > getRequestBody () {
488+ private @ Nullable Mono <Object > getRequestBody () {
473489 for (String key : bindingContext .getModel ().asMap ().keySet ()) {
474490 if (key .startsWith (BindingResult .MODEL_KEY_PREFIX )) {
475491 BindingResult result = (BindingResult ) bindingContext .getModel ().asMap ().get (key );
476- return Mono .just (result .getTarget ());
492+ Object target = result .getTarget ();
493+ if (target != null ) {
494+ return Mono .just (target );
495+ }
477496 }
478497 }
479498 return null ;
@@ -490,7 +509,7 @@ public Publisher<Object> body(@RequestBody Publisher<Object> body) {
490509 protected static class BodySender {
491510
492511 @ ResponseBody
493- public Publisher <Object > body () {
512+ public @ Nullable Publisher <Object > body () {
494513 return null ;
495514 }
496515
0 commit comments