/** * Configure a custom {@link ServerCodecConfigurer}. The provided instance is set on * each created {@link DefaultServerWebExchange}. * <p>By default this is set to {@link ServerCodecConfigurer#create()}. * @param codecConfigurer the codec configurer to use */ public void setCodecConfigurer(ServerCodecConfigurer codecConfigurer) { Assert.notNull(codecConfigurer, "ServerCodecConfigurer is required"); this.codecConfigurer = codecConfigurer; this.enableLoggingRequestDetails = false; this.codecConfigurer.getReaders().stream() .filter(LoggingCodecSupport.class::isInstance) .forEach(reader -> { if (((LoggingCodecSupport) reader).isEnableLoggingRequestDetails()) { this.enableLoggingRequestDetails = true; } }); }
@Override public void afterPropertiesSet() throws Exception { if (CollectionUtils.isEmpty(this.messageReaders)) { ServerCodecConfigurer codecConfigurer = ServerCodecConfigurer.create(); this.messageReaders = codecConfigurer.getReaders(); } if (this.routerFunction == null) { initRouterFunctions(); } }
@Override public HandlerStrategies build() { return new DefaultHandlerStrategies(this.codecConfigurer.getReaders(), this.codecConfigurer.getWriters(), this.viewResolvers, this.webFilters, this.exceptionHandlers, this.localeContextResolver); }
/** * Configure a custom {@link ServerCodecConfigurer}. The provided instance is set on * each created {@link DefaultServerWebExchange}. * <p>By default this is set to {@link ServerCodecConfigurer#create()}. * @param codecConfigurer the codec configurer to use */ public void setCodecConfigurer(ServerCodecConfigurer codecConfigurer) { Assert.notNull(codecConfigurer, "ServerCodecConfigurer is required"); this.codecConfigurer = codecConfigurer; this.enableLoggingRequestDetails = false; this.codecConfigurer.getReaders().stream() .filter(LoggingCodecSupport.class::isInstance) .forEach(reader -> { if (((LoggingCodecSupport) reader).isEnableLoggingRequestDetails()) { this.enableLoggingRequestDetails = true; } }); }
@Override public void afterPropertiesSet() throws Exception { Assert.notNull(this.applicationContext, "ApplicationContext is required"); if (CollectionUtils.isEmpty(this.messageReaders)) { ServerCodecConfigurer codecConfigurer = ServerCodecConfigurer.create(); this.messageReaders = codecConfigurer.getReaders(); } if (this.argumentResolverConfigurer == null) { this.argumentResolverConfigurer = new ArgumentResolverConfigurer(); } if (this.reactiveAdapterRegistry == null) { this.reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance(); } this.methodResolver = new ControllerMethodResolver(this.argumentResolverConfigurer, this.reactiveAdapterRegistry, this.applicationContext, this.messageReaders); this.modelInitializer = new ModelInitializer(this.methodResolver, this.reactiveAdapterRegistry); }
@SuppressWarnings("unchecked") private static Mono<MultiValueMap<String, String>> initFormData(ServerHttpRequest request, ServerCodecConfigurer configurer, String logPrefix) { try { MediaType contentType = request.getHeaders().getContentType(); if (MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(contentType)) { return ((HttpMessageReader<MultiValueMap<String, String>>) configurer.getReaders().stream() .filter(reader -> reader.canRead(FORM_DATA_TYPE, MediaType.APPLICATION_FORM_URLENCODED)) .findFirst() .orElseThrow(() -> new IllegalStateException("No form data HttpMessageReader."))) .readMono(FORM_DATA_TYPE, request, Hints.from(Hints.LOG_PREFIX_HINT, logPrefix)) .switchIfEmpty(EMPTY_FORM_DATA) .cache(); } } catch (InvalidMediaTypeException ex) { // Ignore } return EMPTY_FORM_DATA; }
@SuppressWarnings("unchecked") private static Mono<MultiValueMap<String, Part>> initMultipartData(ServerHttpRequest request, ServerCodecConfigurer configurer, String logPrefix) { try { MediaType contentType = request.getHeaders().getContentType(); if (MediaType.MULTIPART_FORM_DATA.isCompatibleWith(contentType)) { return ((HttpMessageReader<MultiValueMap<String, Part>>) configurer.getReaders().stream() .filter(reader -> reader.canRead(MULTIPART_DATA_TYPE, MediaType.MULTIPART_FORM_DATA)) .findFirst() .orElseThrow(() -> new IllegalStateException("No multipart HttpMessageReader."))) .readMono(MULTIPART_DATA_TYPE, request, Hints.from(Hints.LOG_PREFIX_HINT, logPrefix)) .switchIfEmpty(EMPTY_MULTIPART_DATA) .cache(); } } catch (InvalidMediaTypeException ex) { // Ignore } return EMPTY_MULTIPART_DATA; }
@Bean public RouterFunctionMapping routerFunctionMapping() { RouterFunctionMapping mapping = createRouterFunctionMapping(); mapping.setOrder(-1); // go before RequestMappingHandlerMapping mapping.setMessageReaders(serverCodecConfigurer().getReaders()); mapping.setCorsConfigurations(getCorsConfigurations()); return mapping; }
@SuppressWarnings("unchecked") private static Mono<MultiValueMap<String, String>> initFormData(ServerHttpRequest request, ServerCodecConfigurer configurer, String logPrefix) { try { MediaType contentType = request.getHeaders().getContentType(); if (MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(contentType)) { return ((HttpMessageReader<MultiValueMap<String, String>>) configurer.getReaders().stream() .filter(reader -> reader.canRead(FORM_DATA_TYPE, MediaType.APPLICATION_FORM_URLENCODED)) .findFirst() .orElseThrow(() -> new IllegalStateException("No form data HttpMessageReader."))) .readMono(FORM_DATA_TYPE, request, Hints.from(Hints.LOG_PREFIX_HINT, logPrefix)) .switchIfEmpty(EMPTY_FORM_DATA) .cache(); } } catch (InvalidMediaTypeException ex) { // Ignore } return EMPTY_FORM_DATA; }
@SuppressWarnings("unchecked") private static Mono<MultiValueMap<String, Part>> initMultipartData(ServerHttpRequest request, ServerCodecConfigurer configurer, String logPrefix) { try { MediaType contentType = request.getHeaders().getContentType(); if (MediaType.MULTIPART_FORM_DATA.isCompatibleWith(contentType)) { return ((HttpMessageReader<MultiValueMap<String, Part>>) configurer.getReaders().stream() .filter(reader -> reader.canRead(MULTIPART_DATA_TYPE, MediaType.MULTIPART_FORM_DATA)) .findFirst() .orElseThrow(() -> new IllegalStateException("No multipart HttpMessageReader."))) .readMono(MULTIPART_DATA_TYPE, request, Hints.from(Hints.LOG_PREFIX_HINT, logPrefix)) .switchIfEmpty(EMPTY_MULTIPART_DATA) .cache(); } } catch (InvalidMediaTypeException ex) { // Ignore } return EMPTY_MULTIPART_DATA; }
@Bean public RequestMappingHandlerAdapter requestMappingHandlerAdapter() { RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter(); adapter.setMessageReaders(serverCodecConfigurer().getReaders()); adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer()); adapter.setReactiveAdapterRegistry(webFluxAdapterRegistry()); ArgumentResolverConfigurer configurer = new ArgumentResolverConfigurer(); configureArgumentResolvers(configurer); adapter.setArgumentResolverConfigurer(configurer); return adapter; }
@Test public void defaultReaders() { List<HttpMessageReader<?>> readers = this.configurer.getReaders(); assertEquals(13, readers.size()); assertEquals(ByteArrayDecoder.class, getNextDecoder(readers).getClass()); assertEquals(ByteBufferDecoder.class, getNextDecoder(readers).getClass()); assertEquals(DataBufferDecoder.class, getNextDecoder(readers).getClass()); assertEquals(ResourceDecoder.class, getNextDecoder(readers).getClass()); assertStringDecoder(getNextDecoder(readers), true); assertEquals(ProtobufDecoder.class, getNextDecoder(readers).getClass()); assertEquals(FormHttpMessageReader.class, readers.get(this.index.getAndIncrement()).getClass()); assertEquals(SynchronossPartHttpMessageReader.class, readers.get(this.index.getAndIncrement()).getClass()); assertEquals(MultipartHttpMessageReader.class, readers.get(this.index.getAndIncrement()).getClass()); assertEquals(Jackson2JsonDecoder.class, getNextDecoder(readers).getClass()); assertEquals(Jackson2SmileDecoder.class, getNextDecoder(readers).getClass()); assertEquals(Jaxb2XmlDecoder.class, getNextDecoder(readers).getClass()); assertStringDecoder(getNextDecoder(readers), false); }
@Test public void noMatch() { RouterFunction<ServerResponse> routerFunction = request -> Mono.empty(); RouterFunctionMapping mapping = new RouterFunctionMapping(routerFunction); mapping.setMessageReaders(this.codecConfigurer.getReaders()); Mono<Object> result = mapping.getHandler(this.exchange); StepVerifier.create(result) .expectComplete() .verify(); }
@Test public void normal() { HandlerFunction<ServerResponse> handlerFunction = request -> ServerResponse.ok().build(); RouterFunction<ServerResponse> routerFunction = request -> Mono.just(handlerFunction); RouterFunctionMapping mapping = new RouterFunctionMapping(routerFunction); mapping.setMessageReaders(this.codecConfigurer.getReaders()); Mono<Object> result = mapping.getHandler(this.exchange); StepVerifier.create(result) .expectNext(handlerFunction) .expectComplete() .verify(); }
@Before public void setup() throws Exception { List<HttpMessageReader<?>> readers = ServerCodecConfigurer.create().getReaders(); ReactiveAdapterRegistry registry = ReactiveAdapterRegistry.getSharedInstance(); this.resolver = new RequestPartMethodArgumentResolver(readers, registry); List<HttpMessageWriter<?>> writers = ClientCodecConfigurer.create().getWriters(); this.writer = new MultipartHttpMessageWriter(writers); }
@Test public void requestMappingHandlerAdapter() throws Exception { delegatingConfig.setConfigurers(Collections.singletonList(webFluxConfigurer)); ConfigurableWebBindingInitializer initializer = (ConfigurableWebBindingInitializer) this.delegatingConfig.requestMappingHandlerAdapter().getWebBindingInitializer(); verify(webFluxConfigurer).configureHttpMessageCodecs(codecsConfigurer.capture()); verify(webFluxConfigurer).getValidator(); verify(webFluxConfigurer).getMessageCodesResolver(); verify(webFluxConfigurer).addFormatters(formatterRegistry.capture()); verify(webFluxConfigurer).configureArgumentResolvers(any()); assertNotNull(initializer); assertTrue(initializer.getValidator() instanceof LocalValidatorFactoryBean); assertSame(formatterRegistry.getValue(), initializer.getConversionService()); assertEquals(13, codecsConfigurer.getValue().getReaders().size()); }
@Before public void setup() { ArgumentResolverConfigurer resolvers = new ArgumentResolverConfigurer(); resolvers.addCustomResolver(new CustomArgumentResolver()); resolvers.addCustomResolver(new CustomSyncArgumentResolver()); ServerCodecConfigurer codecs = ServerCodecConfigurer.create(); codecs.customCodecs().decoder(new ByteArrayDecoder()); codecs.customCodecs().decoder(new ByteBufferDecoder()); AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); applicationContext.registerBean(TestControllerAdvice.class); applicationContext.refresh(); this.methodResolver = new ControllerMethodResolver( resolvers, ReactiveAdapterRegistry.getSharedInstance(), applicationContext, codecs.getReaders()); Method method = ResolvableMethod.on(TestController.class).mockCall(TestController::handle).method(); this.handlerMethod = new HandlerMethod(new TestController(), method); }
/** * Error web exception handler error web exception handler. * * @param errorAttributes the error attributes * @return the error web exception handler */ @Bean @Order(Ordered.HIGHEST_PRECEDENCE) public ErrorWebExceptionHandler errorWebExceptionHandler(final ErrorAttributes errorAttributes) { GlobalErrorHandler exceptionHandler = new GlobalErrorHandler( errorAttributes, this.resourceProperties, this.serverProperties.getError(), this.applicationContext); exceptionHandler.setViewResolvers(this.viewResolvers); exceptionHandler.setMessageWriters(this.serverCodecConfigurer.getWriters()); exceptionHandler.setMessageReaders(this.serverCodecConfigurer.getReaders()); return exceptionHandler; }
.getReaders() .stream() .filter(reader -> reader.canRead(elementType, contentType))
public RequestProcessor(FunctionInspector inspector, ObjectProvider<JsonMapper> mapper, StringConverter converter, ObjectProvider<ServerCodecConfigurer> codecs) { this.mapper = mapper.getIfAvailable(); this.inspector = inspector; this.converter = converter; ServerCodecConfigurer source = codecs.getIfAvailable(); this.messageReaders = source == null ? null : source.getReaders(); }