From 0d8eb26ce06833e3baa2d53d934b02565da95cc0 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 13 Nov 2020 14:34:28 +0000 Subject: [PATCH] Use DefaultPartHttpMessageReader with Framework 5.3 Closes gh-703 --- spring-restdocs-webtestclient/build.gradle | 8 ++++- .../WebTestClientRequestConverter.java | 29 ++++++++++++++++--- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/spring-restdocs-webtestclient/build.gradle b/spring-restdocs-webtestclient/build.gradle index f4652f79..2ee3a506 100644 --- a/spring-restdocs-webtestclient/build.gradle +++ b/spring-restdocs-webtestclient/build.gradle @@ -21,4 +21,10 @@ matrixTest { group = 'org.springframework' versions = ['5.1.+', '5.2.+', '5.3.+'] } -} \ No newline at end of file +} + +project.afterEvaluate { + configurations.getByName('testRuntimeClasspath_org.springframework_5.3.+') { + exclude group: 'org.synchronoss.cloud', module: 'nio-multipart-parser' + } +} diff --git a/spring-restdocs-webtestclient/src/main/java/org/springframework/restdocs/webtestclient/WebTestClientRequestConverter.java b/spring-restdocs-webtestclient/src/main/java/org/springframework/restdocs/webtestclient/WebTestClientRequestConverter.java index 97a66382..fb5be55f 100644 --- a/spring-restdocs-webtestclient/src/main/java/org/springframework/restdocs/webtestclient/WebTestClientRequestConverter.java +++ b/spring-restdocs-webtestclient/src/main/java/org/springframework/restdocs/webtestclient/WebTestClientRequestConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 the original author or authors. + * Copyright 2014-2020 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. @@ -33,6 +33,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ReactiveHttpInputMessage; import org.springframework.http.codec.FormHttpMessageReader; +import org.springframework.http.codec.HttpMessageReader; import org.springframework.http.codec.multipart.FilePart; import org.springframework.http.codec.multipart.MultipartHttpMessageReader; import org.springframework.http.codec.multipart.Part; @@ -59,6 +60,8 @@ import org.springframework.util.MultiValueMap; */ class WebTestClientRequestConverter implements RequestConverter { + private static final String DEFAULT_PART_HTTP_MESSAGE_READER = "org.springframework.http.codec.multipart.DefaultPartHttpMessageReader"; + private static final ResolvableType FORM_DATA_TYPE = ResolvableType.forClassWithGenerics(MultiValueMap.class, String.class, String.class); @@ -91,17 +94,35 @@ class WebTestClientRequestConverter implements RequestConverter } private List extractRequestParts(ExchangeResult result) { - if (!ClassUtils.isPresent("org.synchronoss.cloud.nio.multipart.NioMultipartParserListener", - getClass().getClassLoader())) { + HttpMessageReader partHttpMessageReader = findPartHttpMessageReader(); + if (partHttpMessageReader == null) { return Collections.emptyList(); } - return new MultipartHttpMessageReader(new SynchronossPartHttpMessageReader()) + return new MultipartHttpMessageReader(partHttpMessageReader) .readMono(ResolvableType.forClass(Part.class), new ExchangeResultReactiveHttpInputMessage(result), Collections.emptyMap()) .onErrorReturn(new LinkedMultiValueMap<>()).block().values().stream() .flatMap((parts) -> parts.stream().map(this::createOperationRequestPart)).collect(Collectors.toList()); } + @SuppressWarnings("unchecked") + private HttpMessageReader findPartHttpMessageReader() { + if (ClassUtils.isPresent(DEFAULT_PART_HTTP_MESSAGE_READER, getClass().getClassLoader())) { + try { + return (HttpMessageReader) Class + .forName(DEFAULT_PART_HTTP_MESSAGE_READER, true, getClass().getClassLoader()).newInstance(); + } + catch (Exception ex) { + // Continue + } + } + if (ClassUtils.isPresent("org.synchronoss.cloud.nio.multipart.NioMultipartParserListener", + getClass().getClassLoader())) { + return new SynchronossPartHttpMessageReader(); + } + return null; + } + private OperationRequestPart createOperationRequestPart(Part part) { ByteArrayOutputStream content = readPartBodyContent(part); return new OperationRequestPartFactory().create(part.name(),