Add WebInputException subclasses
Closes gh-28142
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -46,6 +46,7 @@ import org.springframework.web.server.MethodNotAllowedException;
|
||||
import org.springframework.web.server.NotAcceptableStatusException;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.ServerWebInputException;
|
||||
import org.springframework.web.server.UnsatisfiedRequestParameterException;
|
||||
import org.springframework.web.server.UnsupportedMediaTypeStatusException;
|
||||
import org.springframework.web.util.pattern.PathPattern;
|
||||
|
||||
@@ -190,7 +191,8 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
|
||||
catch (InvalidMediaTypeException ex) {
|
||||
throw new UnsupportedMediaTypeStatusException(ex.getMessage());
|
||||
}
|
||||
throw new UnsupportedMediaTypeStatusException(contentType, new ArrayList<>(mediaTypes), exchange.getRequest().getMethod());
|
||||
throw new UnsupportedMediaTypeStatusException(
|
||||
contentType, new ArrayList<>(mediaTypes), exchange.getRequest().getMethod());
|
||||
}
|
||||
|
||||
if (helper.hasProducesMismatch()) {
|
||||
@@ -199,9 +201,9 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
|
||||
}
|
||||
|
||||
if (helper.hasParamsMismatch()) {
|
||||
throw new ServerWebInputException(
|
||||
"Expected parameters: " + helper.getParamConditions() +
|
||||
", actual query parameters: " + request.getQueryParams());
|
||||
throw new UnsatisfiedRequestParameterException(
|
||||
helper.getParamConditions().stream().map(Object::toString).toList(),
|
||||
request.getQueryParams());
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -217,10 +219,9 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
|
||||
|
||||
|
||||
public PartialMatchHelper(Set<RequestMappingInfo> infos, ServerWebExchange exchange) {
|
||||
this.partialMatches.addAll(infos.stream().
|
||||
filter(info -> info.getPatternsCondition().getMatchingCondition(exchange) != null).
|
||||
map(info -> new PartialMatch(info, exchange)).
|
||||
collect(Collectors.toList()));
|
||||
this.partialMatches.addAll(infos.stream()
|
||||
.filter(info -> info.getPatternsCondition().getMatchingCondition(exchange) != null)
|
||||
.map(info -> new PartialMatch(info, exchange)).toList());
|
||||
}
|
||||
|
||||
|
||||
@@ -235,42 +236,38 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
|
||||
* Any partial matches for "methods"?
|
||||
*/
|
||||
public boolean hasMethodsMismatch() {
|
||||
return this.partialMatches.stream().
|
||||
noneMatch(PartialMatch::hasMethodsMatch);
|
||||
return this.partialMatches.stream().noneMatch(PartialMatch::hasMethodsMatch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Any partial matches for "methods" and "consumes"?
|
||||
*/
|
||||
public boolean hasConsumesMismatch() {
|
||||
return this.partialMatches.stream().
|
||||
noneMatch(PartialMatch::hasConsumesMatch);
|
||||
return this.partialMatches.stream().noneMatch(PartialMatch::hasConsumesMatch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Any partial matches for "methods", "consumes", and "produces"?
|
||||
*/
|
||||
public boolean hasProducesMismatch() {
|
||||
return this.partialMatches.stream().
|
||||
noneMatch(PartialMatch::hasProducesMatch);
|
||||
return this.partialMatches.stream().noneMatch(PartialMatch::hasProducesMatch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Any partial matches for "methods", "consumes", "produces", and "params"?
|
||||
*/
|
||||
public boolean hasParamsMismatch() {
|
||||
return this.partialMatches.stream().
|
||||
noneMatch(PartialMatch::hasParamsMatch);
|
||||
return this.partialMatches.stream().noneMatch(PartialMatch::hasParamsMatch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return declared HTTP methods.
|
||||
*/
|
||||
public Set<HttpMethod> getAllowedMethods() {
|
||||
return this.partialMatches.stream().
|
||||
flatMap(m -> m.getInfo().getMethodsCondition().getMethods().stream()).
|
||||
map(requestMethod -> HttpMethod.valueOf(requestMethod.name())).
|
||||
collect(Collectors.toSet());
|
||||
return this.partialMatches.stream()
|
||||
.flatMap(m -> m.getInfo().getMethodsCondition().getMethods().stream())
|
||||
.map(requestMethod -> HttpMethod.valueOf(requestMethod.name()))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -278,9 +275,10 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
|
||||
* match the "methods" condition.
|
||||
*/
|
||||
public Set<MediaType> getConsumableMediaTypes() {
|
||||
return this.partialMatches.stream().filter(PartialMatch::hasMethodsMatch).
|
||||
flatMap(m -> m.getInfo().getConsumesCondition().getConsumableMediaTypes().stream()).
|
||||
collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
return this.partialMatches.stream()
|
||||
.filter(PartialMatch::hasMethodsMatch)
|
||||
.flatMap(m -> m.getInfo().getConsumesCondition().getConsumableMediaTypes().stream())
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -288,9 +286,10 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
|
||||
* match the "methods" and "consumes" conditions.
|
||||
*/
|
||||
public Set<MediaType> getProducibleMediaTypes() {
|
||||
return this.partialMatches.stream().filter(PartialMatch::hasConsumesMatch).
|
||||
flatMap(m -> m.getInfo().getProducesCondition().getProducibleMediaTypes().stream()).
|
||||
collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
return this.partialMatches.stream()
|
||||
.filter(PartialMatch::hasConsumesMatch)
|
||||
.flatMap(m -> m.getInfo().getProducesCondition().getProducibleMediaTypes().stream())
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -298,9 +297,10 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
|
||||
* match the "methods", "consumes", and "params" conditions.
|
||||
*/
|
||||
public List<Set<NameValueExpression<String>>> getParamConditions() {
|
||||
return this.partialMatches.stream().filter(PartialMatch::hasProducesMatch).
|
||||
map(match -> match.getInfo().getParamsCondition().getExpressions()).
|
||||
collect(Collectors.toList());
|
||||
return this.partialMatches.stream()
|
||||
.filter(PartialMatch::hasProducesMatch)
|
||||
.map(match -> match.getInfo().getParamsCondition().getExpressions())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -225,8 +225,14 @@ public abstract class AbstractMessageReaderArgumentResolver extends HandlerMetho
|
||||
}
|
||||
|
||||
private ServerWebInputException handleMissingBody(MethodParameter parameter) {
|
||||
String paramInfo = parameter.getExecutable().toGenericString();
|
||||
return new ServerWebInputException("Request body is missing: " + paramInfo, parameter);
|
||||
|
||||
DecodingException cause = new DecodingException(
|
||||
"No request body for: " + parameter.getExecutable().toGenericString());
|
||||
|
||||
ServerWebInputException ex = new ServerWebInputException("No request body", parameter, cause);
|
||||
ex.setDetail("Invalid request content");
|
||||
|
||||
return ex;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -34,6 +34,7 @@ import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.bind.annotation.ValueConstants;
|
||||
import org.springframework.web.reactive.BindingContext;
|
||||
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolverSupport;
|
||||
import org.springframework.web.server.MissingRequestValueException;
|
||||
import org.springframework.web.server.ServerErrorException;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.ServerWebInputException;
|
||||
@@ -244,9 +245,8 @@ public abstract class AbstractNamedValueArgumentResolver extends HandlerMethodAr
|
||||
* @param parameter the method parameter
|
||||
*/
|
||||
protected void handleMissingValue(String name, MethodParameter parameter) {
|
||||
String typeName = parameter.getNestedParameterType().getSimpleName();
|
||||
throw new ServerWebInputException("Missing argument '" + name + "' for method " +
|
||||
"parameter of type " + typeName, parameter);
|
||||
throw new MissingRequestValueException(
|
||||
name, parameter.getNestedParameterType(), "request value", parameter);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -23,8 +23,8 @@ import org.springframework.http.HttpCookie;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.annotation.CookieValue;
|
||||
import org.springframework.web.server.MissingRequestValueException;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.ServerWebInputException;
|
||||
|
||||
/**
|
||||
* Resolve method arguments annotated with {@code @CookieValue}.
|
||||
@@ -76,9 +76,8 @@ public class CookieValueMethodArgumentResolver extends AbstractNamedValueSyncArg
|
||||
|
||||
@Override
|
||||
protected void handleMissingValue(String name, MethodParameter parameter) {
|
||||
String type = parameter.getNestedParameterType().getSimpleName();
|
||||
String reason = "Missing cookie '" + name + "' for method parameter of type " + type;
|
||||
throw new ServerWebInputException(reason, parameter);
|
||||
throw new MissingRequestValueException(
|
||||
name, parameter.getNestedParameterType(), "cookie", parameter);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -31,6 +31,7 @@ import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.MatrixVariable;
|
||||
import org.springframework.web.bind.annotation.ValueConstants;
|
||||
import org.springframework.web.reactive.HandlerMapping;
|
||||
import org.springframework.web.server.MissingRequestValueException;
|
||||
import org.springframework.web.server.ServerErrorException;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.ServerWebInputException;
|
||||
@@ -120,9 +121,8 @@ public class MatrixVariableMethodArgumentResolver extends AbstractNamedValueSync
|
||||
|
||||
@Override
|
||||
protected void handleMissingValue(String name, MethodParameter parameter) throws ServerWebInputException {
|
||||
String paramInfo = parameter.getNestedParameterType().getSimpleName();
|
||||
throw new ServerWebInputException("Missing matrix variable '" + name + "' " +
|
||||
"for method parameter of type " + paramInfo, parameter);
|
||||
throw new MissingRequestValueException(
|
||||
name, parameter.getNestedParameterType(), "path parameter", parameter);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -26,8 +26,8 @@ import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.annotation.RequestAttribute;
|
||||
import org.springframework.web.bind.annotation.ValueConstants;
|
||||
import org.springframework.web.server.MissingRequestValueException;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.ServerWebInputException;
|
||||
|
||||
/**
|
||||
* Resolves method arguments annotated with an @{@link RequestAttribute}.
|
||||
@@ -90,9 +90,8 @@ public class RequestAttributeMethodArgumentResolver extends AbstractNamedValueSy
|
||||
|
||||
@Override
|
||||
protected void handleMissingValue(String name, MethodParameter parameter) {
|
||||
String type = parameter.getNestedParameterType().getSimpleName();
|
||||
String reason = "Missing request attribute '" + name + "' of type " + type;
|
||||
throw new ServerWebInputException(reason, parameter);
|
||||
throw new MissingRequestValueException(
|
||||
name, parameter.getNestedParameterType(), "request attribute", parameter);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -26,8 +26,8 @@ import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.server.MissingRequestValueException;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.ServerWebInputException;
|
||||
|
||||
/**
|
||||
* Resolves method arguments annotated with {@code @RequestHeader} except for
|
||||
@@ -89,9 +89,8 @@ public class RequestHeaderMethodArgumentResolver extends AbstractNamedValueSyncA
|
||||
|
||||
@Override
|
||||
protected void handleMissingValue(String name, MethodParameter parameter) {
|
||||
String type = parameter.getNestedParameterType().getSimpleName();
|
||||
throw new ServerWebInputException("Missing request header '" + name + "' " +
|
||||
"for method parameter of type " + type, parameter);
|
||||
throw new MissingRequestValueException(
|
||||
name, parameter.getNestedParameterType(), "header", parameter);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -28,8 +28,8 @@ import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ValueConstants;
|
||||
import org.springframework.web.server.MissingRequestValueException;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.ServerWebInputException;
|
||||
|
||||
/**
|
||||
* Resolver for method arguments annotated with @{@link RequestParam} from URI
|
||||
@@ -109,9 +109,8 @@ public class RequestParamMethodArgumentResolver extends AbstractNamedValueSyncAr
|
||||
|
||||
@Override
|
||||
protected void handleMissingValue(String name, MethodParameter parameter, ServerWebExchange exchange) {
|
||||
String type = parameter.getNestedParameterType().getSimpleName();
|
||||
String reason = "Required " + type + " parameter '" + name + "' is not present";
|
||||
throw new ServerWebInputException(reason, parameter);
|
||||
throw new MissingRequestValueException(
|
||||
name, parameter.getNestedParameterType(), "query parameter", parameter);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -37,8 +37,8 @@ import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.reactive.BindingContext;
|
||||
import org.springframework.web.server.MissingRequestValueException;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.ServerWebInputException;
|
||||
|
||||
/**
|
||||
* Resolver for {@code @RequestPart} arguments where the named part is decoded
|
||||
@@ -115,8 +115,8 @@ public class RequestPartMethodArgumentResolver extends AbstractMessageReaderArgu
|
||||
List<Part> list = map.get(name);
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
if (isRequired) {
|
||||
String reason = "Required request part '" + name + "' is not present";
|
||||
throw new ServerWebInputException(reason, parameter);
|
||||
throw new MissingRequestValueException(
|
||||
name, parameter.getParameterType(), "request part", parameter);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -24,8 +24,8 @@ import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.annotation.SessionAttribute;
|
||||
import org.springframework.web.bind.annotation.ValueConstants;
|
||||
import org.springframework.web.server.MissingRequestValueException;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.ServerWebInputException;
|
||||
|
||||
/**
|
||||
* Resolves method arguments annotated with an @{@link SessionAttribute}.
|
||||
@@ -62,9 +62,8 @@ public class SessionAttributeMethodArgumentResolver extends AbstractNamedValueAr
|
||||
|
||||
@Override
|
||||
protected void handleMissingValue(String name, MethodParameter parameter) {
|
||||
String type = parameter.getNestedParameterType().getSimpleName();
|
||||
String reason = "Missing session attribute '" + name + "' of type " + type;
|
||||
throw new ServerWebInputException(reason, parameter);
|
||||
throw new MissingRequestValueException(
|
||||
name, parameter.getNestedParameterType(), "session attribute", parameter);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ import org.springframework.web.reactive.result.method.RequestMappingInfo.Builder
|
||||
import org.springframework.web.server.MethodNotAllowedException;
|
||||
import org.springframework.web.server.NotAcceptableStatusException;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.ServerWebInputException;
|
||||
import org.springframework.web.server.UnsatisfiedRequestParameterException;
|
||||
import org.springframework.web.server.UnsupportedMediaTypeStatusException;
|
||||
import org.springframework.web.testfixture.http.server.reactive.MockServerHttpRequest;
|
||||
import org.springframework.web.testfixture.server.MockServerWebExchange;
|
||||
@@ -182,7 +182,7 @@ public class RequestMappingInfoHandlerMappingTests {
|
||||
public void getHandlerTestRequestParamMismatch() {
|
||||
ServerWebExchange exchange = MockServerWebExchange.from(get("/params"));
|
||||
Mono<Object> mono = this.handlerMapping.getHandler(exchange);
|
||||
assertError(mono, ServerWebInputException.class, ex -> {
|
||||
assertError(mono, UnsatisfiedRequestParameterException.class, ex -> {
|
||||
assertThat(ex.getReason()).contains("[foo=bar]");
|
||||
assertThat(ex.getReason()).contains("[bar=baz]");
|
||||
});
|
||||
@@ -212,7 +212,9 @@ public class RequestMappingInfoHandlerMappingTests {
|
||||
exchange = MockServerWebExchange.from(get("/content").accept(MediaType.APPLICATION_JSON));
|
||||
this.handlerMapping.getHandler(exchange).block();
|
||||
|
||||
assertThat(exchange.getAttributes().get(name)).as("Negated expression shouldn't be listed as producible type").isNull();
|
||||
assertThat(exchange.getAttributes().get(name))
|
||||
.as("Negated expression shouldn't be listed as producible type")
|
||||
.isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -352,7 +354,9 @@ public class RequestMappingInfoHandlerMappingTests {
|
||||
ServerWebExchange exchange = MockServerWebExchange.from(request);
|
||||
Mono<Object> mono = this.handlerMapping.getHandler(exchange);
|
||||
|
||||
assertError(mono, UnsupportedMediaTypeStatusException.class, ex -> assertThat(ex.getSupportedMediaTypes()).as("Invalid supported consumable media types").isEqualTo(Collections.singletonList(new MediaType("application", "xml"))));
|
||||
assertError(mono, UnsupportedMediaTypeStatusException.class, ex -> assertThat(ex.getSupportedMediaTypes())
|
||||
.as("Invalid supported consumable media types")
|
||||
.isEqualTo(Collections.singletonList(new MediaType("application", "xml"))));
|
||||
}
|
||||
|
||||
private void testHttpOptions(String requestURI, Set<HttpMethod> allowedMethods, @Nullable MediaType acceptPatch) {
|
||||
@@ -382,7 +386,9 @@ public class RequestMappingInfoHandlerMappingTests {
|
||||
ServerWebExchange exchange = MockServerWebExchange.from(get(url).accept(MediaType.APPLICATION_JSON));
|
||||
Mono<Object> mono = this.handlerMapping.getHandler(exchange);
|
||||
|
||||
assertError(mono, NotAcceptableStatusException.class, ex -> assertThat(ex.getSupportedMediaTypes()).as("Invalid supported producible media types").isEqualTo(Collections.singletonList(new MediaType("application", "xml"))));
|
||||
assertError(mono, NotAcceptableStatusException.class, ex -> assertThat(ex.getSupportedMediaTypes())
|
||||
.as("Invalid supported producible media types")
|
||||
.isEqualTo(Collections.singletonList(new MediaType("application", "xml"))));
|
||||
}
|
||||
|
||||
private void handleMatch(ServerWebExchange exchange, String pattern) {
|
||||
|
||||
Reference in New Issue
Block a user