Reject null for non-optional arguments

Closes gh-33339
This commit is contained in:
Olga Maciaszek-Sharma
2024-08-05 15:30:10 +02:00
committed by rstoyanchev
parent 4ac4c1b868
commit 51de84e148
14 changed files with 378 additions and 81 deletions

View File

@@ -39,6 +39,7 @@ import org.springframework.web.bind.annotation.ValueConstants;
* request header, path variable, cookie, and others.
*
* @author Rossen Stoyanchev
* @author Olga Maciaszek-Sharma
* @since 6.0
*/
public abstract class AbstractNamedValueArgumentResolver implements HttpServiceArgumentResolver {
@@ -145,7 +146,7 @@ public abstract class AbstractNamedValueArgumentResolver implements HttpServiceA
.formatted(parameter.getNestedParameterType().getName()));
}
}
boolean required = (info.required && !parameter.getParameterType().equals(Optional.class));
boolean required = (info.required && !parameter.isOptional());
String defaultValue = (ValueConstants.DEFAULT_NONE.equals(info.defaultValue) ? null : info.defaultValue);
return info.update(name, required, defaultValue);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,8 @@
package org.springframework.web.service.invoker;
import java.util.Optional;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -41,17 +43,26 @@ public class HttpMethodArgumentResolver implements HttpServiceArgumentResolver {
public boolean resolve(
@Nullable Object argument, MethodParameter parameter, HttpRequestValues.Builder requestValues) {
if (!parameter.getParameterType().equals(HttpMethod.class)) {
parameter = parameter.nestedIfOptional();
if (!parameter.getNestedParameterType().equals(HttpMethod.class)) {
return false;
}
Assert.notNull(argument, "HttpMethod is required");
if (argument instanceof Optional<?> optionalValue) {
argument = optionalValue.orElse(null);
}
if (argument == null) {
Assert.isTrue(parameter.isOptional(), "HttpMethod is required");
return true;
}
HttpMethod httpMethod = (HttpMethod) argument;
requestValues.setHttpMethod(httpMethod);
if (logger.isTraceEnabled()) {
logger.trace("Resolved HTTP method to: " + httpMethod.name());
}
return true;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,8 @@
package org.springframework.web.service.invoker;
import java.util.Optional;
import org.springframework.core.MethodParameter;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.ReactiveAdapter;
@@ -30,6 +32,7 @@ import org.springframework.web.bind.annotation.RequestBody;
* annotated arguments.
*
* @author Rossen Stoyanchev
* @author Olga Maciaszek-Sharma
* @since 6.0
*/
public class RequestBodyArgumentResolver implements HttpServiceArgumentResolver {
@@ -68,33 +71,39 @@ public class RequestBodyArgumentResolver implements HttpServiceArgumentResolver
return false;
}
if (argument != null) {
if (this.reactiveAdapterRegistry != null) {
ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(parameter.getParameterType());
if (adapter != null) {
MethodParameter nestedParameter = parameter.nested();
String message = "Async type for @RequestBody should produce value(s)";
Assert.isTrue(!adapter.isNoValue(), message);
Assert.isTrue(nestedParameter.getNestedParameterType() != Void.class, message);
if (requestValues instanceof ReactiveHttpRequestValues.Builder reactiveRequestValues) {
reactiveRequestValues.setBodyPublisher(
adapter.toPublisher(argument), asParameterizedTypeRef(nestedParameter));
}
else {
throw new IllegalStateException(
"RequestBody with a reactive type is only supported with reactive client");
}
return true;
}
}
// Not a reactive type
requestValues.setBodyValue(argument);
if (argument instanceof Optional<?> optionalValue) {
argument = optionalValue.orElse(null);
}
if (argument == null) {
Assert.isTrue(!annot.required() || parameter.isOptional(), "RequestBody is required");
return true;
}
if (this.reactiveAdapterRegistry != null) {
ReactiveAdapter adapter = this.reactiveAdapterRegistry
.getAdapter(parameter.getParameterType());
if (adapter != null) {
MethodParameter nestedParameter = parameter.nested();
String message = "Async type for @RequestBody should produce value(s)";
Assert.isTrue(!adapter.isNoValue(), message);
Assert.isTrue(nestedParameter.getNestedParameterType() != Void.class, message);
if (requestValues instanceof ReactiveHttpRequestValues.Builder reactiveRequestValues) {
reactiveRequestValues.setBodyPublisher(
adapter.toPublisher(argument), asParameterizedTypeRef(nestedParameter));
}
else {
throw new IllegalStateException(
"RequestBody with a reactive type is only supported with reactive client");
}
return true;
}
}
// Not a reactive type
requestValues.setBodyValue(argument);
return true;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,9 +17,11 @@
package org.springframework.web.service.invoker;
import java.net.URL;
import java.util.Optional;
import org.springframework.core.MethodParameter;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.web.util.UriBuilderFactory;
import org.springframework.web.util.UriTemplate;
@@ -42,14 +44,22 @@ public class UriBuilderFactoryArgumentResolver implements HttpServiceArgumentRes
public boolean resolve(
@Nullable Object argument, MethodParameter parameter, HttpRequestValues.Builder requestValues) {
if (!parameter.getParameterType().equals(UriBuilderFactory.class)) {
parameter = parameter.nestedIfOptional();
if (!parameter.getNestedParameterType().equals(UriBuilderFactory.class)) {
return false;
}
if (argument != null) {
requestValues.setUriBuilderFactory((UriBuilderFactory) argument);
if (argument instanceof Optional<?> optionalValue) {
argument = optionalValue.orElse(null);
}
if (argument == null) {
Assert.isTrue(parameter.isOptional(), "UriBuilderFactory is required");
return true;
}
requestValues.setUriBuilderFactory((UriBuilderFactory) argument);
return true;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,15 +17,18 @@
package org.springframework.web.service.invoker;
import java.net.URI;
import java.util.Optional;
import org.springframework.core.MethodParameter;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* {@link HttpServiceArgumentResolver} that resolves the URL for the request
* from a {@link URI} argument.
*
* @author Rossen Stoyanchev
* @author Olga Maciaszek-Sharma
* @since 6.0
*/
public class UrlArgumentResolver implements HttpServiceArgumentResolver {
@@ -34,14 +37,22 @@ public class UrlArgumentResolver implements HttpServiceArgumentResolver {
public boolean resolve(
@Nullable Object argument, MethodParameter parameter, HttpRequestValues.Builder requestValues) {
if (!parameter.getParameterType().equals(URI.class)) {
parameter = parameter.nestedIfOptional();
if (!parameter.getNestedParameterType().equals(URI.class)) {
return false;
}
if (argument != null) {
requestValues.setUri((URI) argument);
if (argument instanceof Optional<?> optionalValue) {
argument = optionalValue.orElse(null);
}
if (argument == null) {
Assert.isTrue(parameter.isOptional(), "URI is required");
return true;
}
requestValues.setUri((URI) argument);
return true;
}