Fix --content-type and --data inputs in curl command

content-type needs to be parsed (no automatic parsing from String)

data was splitting on commas, meaning --data="key=value1,value2" was sent to the server as "key=value1&value2"

NOTE - you'd expect there to already be a "do nothing splitter", right? But there isn't :/

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=223346887
This commit is contained in:
guyben 2018-11-29 08:04:09 -08:00 committed by jianglai
parent 5d2bb892f3
commit 849ea0e0f3
2 changed files with 67 additions and 0 deletions

View file

@ -14,11 +14,15 @@
package google.registry.tools; package google.registry.tools;
import static com.google.common.base.Preconditions.checkArgument;
import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.charset.StandardCharsets.UTF_8;
import com.beust.jcommander.IStringConverter;
import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters; import com.beust.jcommander.Parameters;
import com.beust.jcommander.converters.IParameterSplitter;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.net.MediaType; import com.google.common.net.MediaType;
@ -50,6 +54,7 @@ class CurlCommand implements CommandWithConnection {
@Parameter( @Parameter(
names = {"-t", "--content-type"}, names = {"-t", "--content-type"},
converter = MediaTypeConverter.class,
description = description =
"Media type of the request body (for a POST request. Must be combined with --body)") "Media type of the request body (for a POST request. Must be combined with --body)")
private MediaType mimeType = MediaType.PLAIN_TEXT_UTF_8; private MediaType mimeType = MediaType.PLAIN_TEXT_UTF_8;
@ -58,6 +63,7 @@ class CurlCommand implements CommandWithConnection {
// GET...) // GET...)
@Parameter( @Parameter(
names = {"-d", "--data"}, names = {"-d", "--data"},
splitter = NoSplittingSplitter.class,
description = description =
"Body for a post request. If specified, a POST request is sent. If " "Body for a post request. If specified, a POST request is sent. If "
+ "absent, a GET request is sent.") + "absent, a GET request is sent.")
@ -95,4 +101,20 @@ class CurlCommand implements CommandWithConnection {
Joiner.on("&").join(data).getBytes(UTF_8)); Joiner.on("&").join(data).getBytes(UTF_8));
System.out.println(response); System.out.println(response);
} }
public static class MediaTypeConverter implements IStringConverter<MediaType> {
@Override
public MediaType convert(String mediaType) {
List<String> parts = Splitter.on('/').splitToList(mediaType);
checkArgument(parts.size() == 2, "invalid MediaType '%s'", mediaType);
return MediaType.create(parts.get(0), parts.get(1)).withCharset(UTF_8);
}
}
public static class NoSplittingSplitter implements IParameterSplitter {
@Override
public List<String> split(String value) {
return ImmutableList.of(value);
}
}
} }

View file

@ -79,6 +79,37 @@ public class CurlCommandTest extends CommandTestCase<CurlCommand> {
eq("some data".getBytes(UTF_8))); eq("some data".getBytes(UTF_8)));
} }
@Test
public void testPostInvocation_withContentType() throws Exception {
runCommand(
"--path=/foo/bar?a=1&b=2",
"--data=some data",
"--service=DEFAULT",
"--content-type=application/json");
verify(connection).withService(DEFAULT);
verifyNoMoreInteractions(connection);
verify(connectionForService)
.sendPostRequest(
eq("/foo/bar?a=1&b=2"),
eq(ImmutableMap.<String, String>of()),
eq(MediaType.JSON_UTF_8),
eq("some data".getBytes(UTF_8)));
}
@Test
public void testPostInvocation_badContentType() throws Exception {
assertThrows(
IllegalArgumentException.class,
() ->
runCommand(
"--path=/foo/bar?a=1&b=2",
"--data=some data",
"--service=DEFAULT",
"--content-type=bad"));
verifyNoMoreInteractions(connection);
verifyNoMoreInteractions(connectionForService);
}
@Test @Test
public void testMultiDataPost() throws Exception { public void testMultiDataPost() throws Exception {
runCommand( runCommand(
@ -93,6 +124,20 @@ public class CurlCommandTest extends CommandTestCase<CurlCommand> {
eq("first=100&second=200".getBytes(UTF_8))); eq("first=100&second=200".getBytes(UTF_8)));
} }
@Test
public void testDataDoesntSplit() throws Exception {
runCommand(
"--path=/foo/bar?a=1&b=2", "--data=one,two", "--service=PUBAPI");
verify(connection).withService(PUBAPI);
verifyNoMoreInteractions(connection);
verify(connectionForService)
.sendPostRequest(
eq("/foo/bar?a=1&b=2"),
eq(ImmutableMap.<String, String>of()),
eq(MediaType.PLAIN_TEXT_UTF_8),
eq("one,two".getBytes(UTF_8)));
}
@Test @Test
public void testExplicitPostInvocation() throws Exception { public void testExplicitPostInvocation() throws Exception {
runCommand("--path=/foo/bar?a=1&b=2", "--request=POST", "--service=TOOLS"); runCommand("--path=/foo/bar?a=1&b=2", "--request=POST", "--service=TOOLS");