/** * Read the body from a method argument with {@link HttpMessageReader}. * @param bodyParameter the {@link MethodParameter} to read * @param isBodyRequired true if the body is required * @param bindingContext the binding context to use * @param exchange the current exchange * @return the body * @see #readBody(MethodParameter, MethodParameter, boolean, BindingContext, ServerWebExchange) */ protected Mono<Object> readBody(MethodParameter bodyParameter, boolean isBodyRequired, BindingContext bindingContext, ServerWebExchange exchange) { return this.readBody(bodyParameter, null, isBodyRequired, bindingContext, exchange); }
ResolvableType actualType = (actualParam != null ? ResolvableType.forMethodParameter(actualParam) : bodyType); Class<?> resolvedType = bodyType.resolve(); ReactiveAdapter adapter = (resolvedType != null ? getAdapterRegistry().getAdapter(resolvedType) : null); ResolvableType elementType = (adapter != null ? bodyType.getGeneric() : bodyType); isBodyRequired = isBodyRequired || (adapter != null && !adapter.supportsEmpty()); Object[] hints = extractValidationHints(bodyParam); for (HttpMessageReader<?> reader : getMessageReaders()) { if (reader.canRead(elementType, mediaType)) { Map<String, Object> readHints = Hints.from(Hints.LOG_PREFIX_HINT, exchange.getLogPrefix()); flux = flux.onErrorResume(ex -> Flux.error(handleReadError(bodyParam, ex))); if (isBodyRequired) { flux = flux.switchIfEmpty(Flux.error(() -> handleMissingBody(bodyParam))); validate(target, hints, bodyParam, bindingContext, exchange)); mono = mono.onErrorResume(ex -> Mono.error(handleReadError(bodyParam, ex))); if (isBodyRequired) { mono = mono.switchIfEmpty(Mono.error(() -> handleMissingBody(bodyParam))); validate(target, hints, bodyParam, bindingContext, exchange)); }); if (isBodyRequired) { body = body.switchIfEmpty(Mono.error(() -> handleMissingBody(bodyParam)));
ReactiveAdapter adapter = getAdapterRegistry().getAdapter(bodyType.resolve()); for (HttpMessageReader<?> reader : getMessageReaders()) { flux = reader.read(elementType, request, readHints); flux = flux.onErrorResumeWith(ex -> Flux.error(wrapReadError(ex, bodyParameter))); if (checkRequired(adapter, isBodyRequired)) { flux = flux.switchIfEmpty(Flux.error(getRequiredBodyError(bodyParameter))); Object[] hints = extractValidationHints(bodyParameter); if (hints != null) { flux = flux.doOnNext(target -> validate(target, hints, bodyParameter, bindingContext, exchange)); mono = reader.readMono(elementType, request, readHints); mono = mono.otherwise(ex -> Mono.error(wrapReadError(ex, bodyParameter))); if (checkRequired(adapter, isBodyRequired)) { mono = mono.otherwiseIfEmpty(Mono.error(getRequiredBodyError(bodyParameter))); Object[] hints = extractValidationHints(bodyParameter); if (hints != null) { mono = mono.doOnNext(target -> validate(target, hints, bodyParameter, bindingContext, exchange));
@SuppressWarnings("unchecked") private <T> T resolveValue(MethodParameter param, String body) { MockServerHttpRequest request = post("/path").contentType(MediaType.APPLICATION_JSON).body(body); ServerWebExchange exchange = MockServerWebExchange.from(request); Mono<Object> result = this.resolver.readBody(param, true, this.bindingContext, exchange); Object value = result.block(Duration.ofSeconds(5)); assertNotNull(value); assertTrue("Unexpected return value type: " + value, param.getParameterType().isAssignableFrom(value.getClass())); return (T) value; }
@SuppressWarnings("unchecked") @Test public void missingContentType() throws Exception { MockServerHttpRequest request = post("/path").body("{\"bar\":\"BARBAR\",\"foo\":\"FOOFOO\"}"); ServerWebExchange exchange = MockServerWebExchange.from(request); ResolvableType type = forClassWithGenerics(Mono.class, TestBean.class); MethodParameter param = this.testMethod.arg(type); Mono<Object> result = this.resolver.readBody(param, true, this.bindingContext, exchange); Mono<TestBean> value = (Mono<TestBean>) result.block(Duration.ofSeconds(1)); StepVerifier.create(value).expectError(UnsupportedMediaTypeStatusException.class).verify(); }
@Test @SuppressWarnings("unchecked") // SPR-9942 public void emptyBody() throws Exception { MockServerHttpRequest request = post("/path").contentType(MediaType.APPLICATION_JSON).build(); ServerWebExchange exchange = MockServerWebExchange.from(request); ResolvableType type = forClassWithGenerics(Mono.class, TestBean.class); MethodParameter param = this.testMethod.arg(type); Mono<TestBean> result = (Mono<TestBean>) this.resolver.readBody( param, true, this.bindingContext, exchange).block(); StepVerifier.create(result).expectError(ServerWebInputException.class).verify(); }