Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;

import org.springframework.util.LinkedMultiValueMap;
Expand All @@ -16,6 +14,7 @@
* A request's form parameters, derived from its form URL encoded body content.
*
* @author Andy Wilkinson
* @author Minju Kim
* @since 3.0.0
*/
public final class FormParameters extends LinkedMultiValueMap<String, String> {
Expand Down Expand Up @@ -54,20 +53,12 @@ private static FormParameters parse(String bodyContent) {
}

private static void processParameter(String parameter, FormParameters parameters) {
String[] components = parameter.split("=");
if (components.length > 0 && components.length < 3) {
if (components.length == 2) {
String name = components[0];
String value = components[1];
parameters.add(decode(name), decode(value));
}
else {
List<String> values = parameters.computeIfAbsent(components[0], (p) -> new LinkedList<>());
values.add("");
}
int separator = parameter.indexOf('=');
if (separator != -1) {
parameters.add(decode(parameter.substring(0, separator)), decode(parameter.substring(separator + 1)));
}
else {
throw new IllegalArgumentException("The parameter '" + parameter + "' is malformed");
parameters.add(decode(parameter), "");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@

import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;

import org.springframework.util.LinkedMultiValueMap;
Expand All @@ -16,6 +14,7 @@
* A request's query parameters, derived from its URI's query string.
*
* @author Andy Wilkinson
* @author Minju Kim
* @since 3.0.0
*/
public final class QueryParameters extends LinkedMultiValueMap<String, String> {
Expand Down Expand Up @@ -54,20 +53,12 @@ private static QueryParameters parse(String query) {
}

private static void processParameter(String parameter, QueryParameters parameters) {
String[] components = parameter.split("=");
if (components.length > 0 && components.length < 3) {
if (components.length == 2) {
String name = components[0];
String value = components[1];
parameters.add(decode(name), decode(value));
}
else {
List<String> values = parameters.computeIfAbsent(components[0], (p) -> new LinkedList<>());
values.add("");
}
int separator = parameter.indexOf('=');
if (separator != -1) {
parameters.add(decode(parameter.substring(0, separator)), decode(parameter.substring(separator + 1)));
}
else {
throw new IllegalArgumentException("The parameter '" + parameter + "' is malformed");
parameters.add(decode(parameter), "");
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* Copyright 2014-present the original author or authors.
*/

package org.springframework.restdocs.operation;

import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Collections;

import org.junit.jupiter.api.Test;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;

import static org.assertj.core.api.Assertions.assertThat;

/**
* Tests for {@link FormParameters}.
*
* @author Minju Kim
*/
class FormParametersTests {

@Test
void noContent() {
FormParameters parameters = formParameters("");
assertThat(parameters).isEmpty();
}

@Test
void singleParameter() {
FormParameters parameters = formParameters("a=alpha");
assertThat(parameters).containsOnlyKeys("a");
assertThat(parameters.get("a")).containsExactly("alpha");
}

@Test
void multipleParameters() {
FormParameters parameters = formParameters("a=alpha&b=bravo&a=apple");
assertThat(parameters).containsOnlyKeys("a", "b");
assertThat(parameters.get("a")).containsExactly("alpha", "apple");
assertThat(parameters.get("b")).containsExactly("bravo");
}

@Test
void parameterWithNoValue() {
FormParameters parameters = formParameters("a");
assertThat(parameters).containsOnlyKeys("a");
assertThat(parameters.get("a")).containsExactly("");
}

@Test
void parameterWithEmptyValue() {
FormParameters parameters = formParameters("a=");
assertThat(parameters).containsOnlyKeys("a");
assertThat(parameters.get("a")).containsExactly("");
}

@Test
void encodedParameter() {
FormParameters parameters = formParameters("a+b=c%26d");
assertThat(parameters).containsOnlyKeys("a b");
assertThat(parameters.get("a b")).containsExactly("c&d");
}

@Test
void encodedParameterWithNoValue() {
FormParameters parameters = formParameters("a+b");
assertThat(parameters).containsOnlyKeys("a b");
assertThat(parameters.get("a b")).containsExactly("");
}

@Test
void parameterWithValueContainingEquals() {
FormParameters parameters = formParameters("filter=name==bob");
assertThat(parameters).containsOnlyKeys("filter");
assertThat(parameters.get("filter")).containsExactly("name==bob");
}

@Test
void parameterWithValueEndingWithEquals() {
FormParameters parameters = formParameters("cursor=YWJj==");
assertThat(parameters).containsOnlyKeys("cursor");
assertThat(parameters.get("cursor")).containsExactly("YWJj==");
}

private FormParameters formParameters(String content) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
return FormParameters.from(new OperationRequestFactory().create(URI.create("http://localhost"), HttpMethod.POST,
content.getBytes(StandardCharsets.UTF_8), headers, Collections.emptyList()));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* Copyright 2014-present the original author or authors.
*/

package org.springframework.restdocs.operation;

import java.net.URI;
import java.util.Collections;

import org.junit.jupiter.api.Test;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;

import static org.assertj.core.api.Assertions.assertThat;

/**
* Tests for {@link QueryParameters}.
*
* @author Minju Kim
*/
class QueryParametersTests {

@Test
void noQueryString() {
QueryParameters parameters = queryParameters("http://localhost");
assertThat(parameters).isEmpty();
}

@Test
void singleParameter() {
QueryParameters parameters = queryParameters("http://localhost?a=alpha");
assertThat(parameters).containsOnlyKeys("a");
assertThat(parameters.get("a")).containsExactly("alpha");
}

@Test
void multipleParameters() {
QueryParameters parameters = queryParameters("http://localhost?a=alpha&b=bravo&a=apple");
assertThat(parameters).containsOnlyKeys("a", "b");
assertThat(parameters.get("a")).containsExactly("alpha", "apple");
assertThat(parameters.get("b")).containsExactly("bravo");
}

@Test
void parameterWithNoValue() {
QueryParameters parameters = queryParameters("http://localhost?a");
assertThat(parameters).containsOnlyKeys("a");
assertThat(parameters.get("a")).containsExactly("");
}

@Test
void parameterWithEmptyValue() {
QueryParameters parameters = queryParameters("http://localhost?a=");
assertThat(parameters).containsOnlyKeys("a");
assertThat(parameters.get("a")).containsExactly("");
}

@Test
void encodedParameter() {
QueryParameters parameters = queryParameters("http://localhost?a%20b=c%26d");
assertThat(parameters).containsOnlyKeys("a b");
assertThat(parameters.get("a b")).containsExactly("c&d");
}

@Test
void encodedParameterWithNoValue() {
QueryParameters parameters = queryParameters("http://localhost?a%20b");
assertThat(parameters).containsOnlyKeys("a b");
assertThat(parameters.get("a b")).containsExactly("");
}

@Test
void parameterWithValueContainingEquals() {
QueryParameters parameters = queryParameters("http://localhost?filter=name==bob");
assertThat(parameters).containsOnlyKeys("filter");
assertThat(parameters.get("filter")).containsExactly("name==bob");
}

@Test
void parameterWithValueEndingWithEquals() {
QueryParameters parameters = queryParameters("http://localhost?cursor=YWJj==");
assertThat(parameters).containsOnlyKeys("cursor");
assertThat(parameters.get("cursor")).containsExactly("YWJj==");
}

private QueryParameters queryParameters(String uri) {
return QueryParameters.from(new OperationRequestFactory().create(URI.create(uri), HttpMethod.GET, new byte[0],
new HttpHeaders(), Collections.emptyList()));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
Expand Down Expand Up @@ -46,6 +45,7 @@
*
* @author Andy Wilkinson
* @author Clyde Stubbs
* @author Minju Kim
*/
class MockMvcRequestConverter implements RequestConverter<MockHttpServletRequest> {

Expand Down Expand Up @@ -254,20 +254,12 @@ private static MultiValueMap<String, String> parse(@Nullable String query) {
}

private static void processParameter(String parameter, MultiValueMap<String, String> parameters) {
String[] components = parameter.split("=");
if (components.length > 0 && components.length < 3) {
if (components.length == 2) {
String name = components[0];
String value = components[1];
parameters.add(decode(name), decode(value));
}
else {
List<String> values = parameters.computeIfAbsent(components[0], (p) -> new LinkedList<>());
values.add("");
}
int separator = parameter.indexOf('=');
if (separator != -1) {
parameters.add(decode(parameter.substring(0, separator)), decode(parameter.substring(separator + 1)));
}
else {
throw new IllegalArgumentException("The parameter '" + parameter + "' is malformed");
parameters.add(decode(parameter), "");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,24 @@ void postRequestWithNonAsciiParametersAndQueryStringCreatesFormUrlEncodedContent
assertThat(request.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_FORM_URLENCODED);
}

@Test
void postRequestWithQueryStringParameterWithValueContainingEquals() {
OperationRequest request = createOperationRequest(
MockMvcRequestBuilders.post(URI.create("/foo?filter=name==bob")));
assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo?filter=name==bob"));
assertThat(request.getMethod()).isEqualTo(HttpMethod.POST);
assertThat(request.getContentAsString()).isEmpty();
}

@Test
void postRequestWithQueryStringParameterWithValueEndingWithEqualsDoesNotDuplicateItInContent() {
OperationRequest request = createOperationRequest(
MockMvcRequestBuilders.post(URI.create("/foo?cursor=YWJj==")));
assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo?cursor=YWJj=="));
assertThat(request.getMethod()).isEqualTo(HttpMethod.POST);
assertThat(request.getContentAsString()).isEmpty();
}

@Test
void mockMultipartFileUpload() {
OperationRequest request = createOperationRequest(MockMvcRequestBuilders.multipart("/foo")
Expand Down
Loading