Skip to content
This repository was archived by the owner on Dec 19, 2023. It is now read-only.

Commit 2a23c31

Browse files
MikeSafonovfbenz
authored andcommitted
Replacement for binary content of multipart requests (#369)
* feat: added MultipartContentOperationPreprocessor for replacing binary content of multipart/form-data requests * docs: add MultipartContentOperationPreprocessor to docs
1 parent 2559b34 commit 2a23c31

File tree

4 files changed

+133
-0
lines changed

4 files changed

+133
-0
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package capital.scalable.restdocs.response;
2+
3+
import org.springframework.http.HttpHeaders;
4+
import org.springframework.http.MediaType;
5+
import org.springframework.restdocs.operation.OperationRequest;
6+
import org.springframework.restdocs.operation.OperationRequestFactory;
7+
import org.springframework.restdocs.operation.OperationRequestPart;
8+
import org.springframework.restdocs.operation.OperationRequestPartFactory;
9+
import org.springframework.restdocs.operation.preprocess.OperationPreprocessorAdapter;
10+
11+
import java.util.List;
12+
13+
import static java.nio.charset.StandardCharsets.UTF_8;
14+
import static java.util.stream.Collectors.toList;
15+
16+
public class MultipartContentOperationPreprocessor extends OperationPreprocessorAdapter {
17+
private static final byte[] BINARY_REPLACEMENT = "<binary>".getBytes(UTF_8);
18+
19+
private final OperationRequestPartFactory partFactory = new OperationRequestPartFactory();
20+
private final OperationRequestFactory requestFactory = new OperationRequestFactory();
21+
22+
@Override
23+
public OperationRequest preprocess(OperationRequest request) {
24+
if (isMultipart(request)) {
25+
List<OperationRequestPart> parts = request.getParts().stream()
26+
.map(this::replaceBinary)
27+
.collect(toList());
28+
return requestFactory.create(request.getUri(),
29+
request.getMethod(), request.getContent(), request.getHeaders(), request.getParameters()
30+
, parts);
31+
}
32+
return request;
33+
}
34+
35+
private boolean isMultipart(OperationRequest request) {
36+
List<String> contentTypes = request.getHeaders().get(HttpHeaders.CONTENT_TYPE);
37+
return contentTypes != null && contentTypes.contains(MediaType.MULTIPART_FORM_DATA_VALUE);
38+
}
39+
40+
private OperationRequestPart replaceBinary(OperationRequestPart part) {
41+
return partFactory.create(part.getName(), part.getSubmittedFileName()
42+
, BINARY_REPLACEMENT, part.getHeaders());
43+
}
44+
}

spring-auto-restdocs-core/src/main/java/capital/scalable/restdocs/response/ResponseModifyingPreprocessors.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,15 @@ public static OperationPreprocessor replaceBinaryContent() {
4949
return new ContentModifyingOperationPreprocessor(new BinaryReplacementContentModifier());
5050
}
5151

52+
/**
53+
* For binary content of multipart/form-data requests, replaces value with "&lt;binary&gt;".
54+
*
55+
* @return a preprocessor replacing binary content of multipart/form-data requests
56+
*/
57+
public static OperationPreprocessor replaceMultipartBinaryContent() {
58+
return new MultipartContentOperationPreprocessor();
59+
}
60+
5261
/**
5362
* For JSON content, cuts the length of all JSON arrays in the response to 3 elements.
5463
*
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package capital.scalable.restdocs.response;
2+
3+
import org.junit.Before;
4+
import org.junit.Test;
5+
import org.springframework.http.HttpHeaders;
6+
import org.springframework.http.HttpMethod;
7+
import org.springframework.http.MediaType;
8+
import org.springframework.restdocs.operation.OperationRequest;
9+
import org.springframework.restdocs.operation.OperationRequestFactory;
10+
import org.springframework.restdocs.operation.OperationRequestPart;
11+
import org.springframework.restdocs.operation.OperationRequestPartFactory;
12+
import org.springframework.restdocs.operation.Parameters;
13+
14+
import java.net.URI;
15+
import java.net.URISyntaxException;
16+
import java.nio.charset.StandardCharsets;
17+
import java.util.ArrayList;
18+
import java.util.List;
19+
20+
import static org.junit.Assert.assertArrayEquals;
21+
import static org.junit.Assert.assertEquals;
22+
23+
public class MultipartContentOperationPreprocessorTest {
24+
private static final byte[] EXPECTED_CONTENT = "<binary>".getBytes(StandardCharsets.UTF_8);
25+
private static final byte[] BINARY_CONTENT = new byte[]{1, 2, 3, 3, 3};
26+
private MultipartContentOperationPreprocessor preprocessor;
27+
private OperationRequestFactory requestFactory;
28+
private OperationRequestPartFactory partFactory;
29+
30+
@Before
31+
public void setUp() {
32+
preprocessor = new MultipartContentOperationPreprocessor();
33+
requestFactory = new OperationRequestFactory();
34+
partFactory = new OperationRequestPartFactory();
35+
}
36+
37+
@Test
38+
public void shouldReplaceContent() throws URISyntaxException {
39+
OperationRequest request = createRequestWithContentType(MediaType.MULTIPART_FORM_DATA_VALUE);
40+
41+
OperationRequest processedRequest = preprocessor.preprocess(request);
42+
assertArrayEquals(request.getContent(), processedRequest.getContent());
43+
assertEquals(request.getHeaders(), processedRequest.getHeaders());
44+
assertEquals(request.getMethod(), processedRequest.getMethod());
45+
assertEquals(request.getUri(), processedRequest.getUri());
46+
assertEquals(request.getParameters(), processedRequest.getParameters());
47+
for (OperationRequestPart part : processedRequest.getParts()) {
48+
assertArrayEquals(EXPECTED_CONTENT, part.getContent());
49+
}
50+
}
51+
52+
@Test
53+
public void shouldNotReplaceWhenNotMultipart() throws URISyntaxException {
54+
OperationRequest request = createRequestWithContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
55+
56+
OperationRequest processedRequest = preprocessor.preprocess(request);
57+
assertArrayEquals(request.getContent(), processedRequest.getContent());
58+
assertEquals(request.getHeaders(), processedRequest.getHeaders());
59+
assertEquals(request.getMethod(), processedRequest.getMethod());
60+
assertEquals(request.getUri(), processedRequest.getUri());
61+
assertEquals(request.getParameters(), processedRequest.getParameters());
62+
63+
OperationRequestPart[] expectedParts = request.getParts().toArray(new OperationRequestPart[0]);
64+
OperationRequestPart[] operationRequestParts = processedRequest.getParts().toArray(new OperationRequestPart[0]);
65+
for (int i = 0; i < operationRequestParts.length; i++) {
66+
assertEquals(expectedParts[i], operationRequestParts[i]);
67+
}
68+
}
69+
70+
private OperationRequest createRequestWithContentType(String contentType) throws URISyntaxException {
71+
HttpHeaders headers = new HttpHeaders();
72+
headers.add(HttpHeaders.CONTENT_TYPE, contentType);
73+
Parameters parameters = new Parameters();
74+
parameters.add("parameter", "value");
75+
List<OperationRequestPart> requestParts = new ArrayList<>();
76+
requestParts.add(partFactory.create("first", "file1", BINARY_CONTENT, new HttpHeaders()));
77+
return requestFactory.create(new URI("http://localhost"), HttpMethod.POST, BINARY_CONTENT, headers, parameters, requestParts);
78+
}
79+
}

spring-auto-restdocs-docs/other.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ See example project for link:{example-dir}/src/main/asciidoc/index.adoc#overview
2222
Preprocessors are available for use in order to improve quality of endpoint examples.
2323

2424
- link:{core-package}/response/BinaryReplacementContentModifier.java[binary replacement]: replaces content with `<binary>` for common mime types
25+
- link:{core-package}/response/MultipartContentOperationPreprocessor.java[multipart binary replacement]: replaces content with `<binary>` for multipart/form-data requests
2526
- link:{core-package}/response/ArrayLimitingJsonContentModifier.java[limit JSON array length]: limits all JSON arrays to 3 items
2627

2728
For a list of standard preprocessors see link:{restdocs-package}/operation/preprocess/Preprocessors.java[Preprocessors].

0 commit comments

Comments
 (0)