Skip to content

Instantly share code, notes, and snippets.

@jebeaudet
Last active September 14, 2024 14:55
Show Gist options
  • Save jebeaudet/603f4efb15e45257b60cee3d0d60cb63 to your computer and use it in GitHub Desktop.
Save jebeaudet/603f4efb15e45257b60cee3d0d60cb63 to your computer and use it in GitHub Desktop.
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class RequestEncodingTest
{
@LocalServerPort
private int port;
private RequestEncodingApi client;
@BeforeEach
void setUp()
{
client = Feign.builder()
.contract(new SpringMvcContract())
.client(new ApacheHttp5Client())
.dismiss404()
.target(RequestEncodingApi.class, "http://localhost:" + port);
}
@ParameterizedTest
@MethodSource(value = "inputs")
void givenEncodedPathParameter_whenQueryingApi_thenShouldReturnProperEncoding(String parameter) throws Exception
{
assertThat(client.pathParameterGet(parameter)).isEqualTo(parameter);
assertThat(client.pathParameterPost(parameter)).isEqualTo(parameter);
assertThat(client.pathParameterPut(parameter)).isEqualTo(parameter);
}
@ParameterizedTest
@MethodSource(value = "inputs")
void givenEncodedRequestParameter_whenQueryingApi_thenShouldReturnProperEncoding(String parameter) throws Exception
{
assertThat(client.requestParameterGet(parameter)).isEqualTo(parameter);
assertThat(client.requestParameterPost(parameter)).isEqualTo(parameter);
assertThat(client.requestParameterPut(parameter)).isEqualTo(parameter);
}
@Test
void givenNullRequestParameter_whenQueryingApi_thenShouldReturnBlank() throws Exception
{
// Spring will receive a null value. Since it returns an empty response, Feign's StringDecoder decodes it as ""
assertThat(client.requestParameterGet(null)).isEqualTo("");
assertThat(client.requestParameterPost(null)).isEqualTo("");
assertThat(client.requestParameterPut(null)).isEqualTo("");
}
@Test
void givenNullPathParameter_whenQueryingApi_thenShouldReturnBlank() throws Exception
{
assertThat(client.requestParameterGet(null)).isEqualTo("");
assertThat(client.requestParameterPost(null)).isEqualTo("");
assertThat(client.requestParameterPut(null)).isEqualTo("");
}
static Stream<Arguments> inputs()
{
return Stream.of("patate",
"patate patate",
"patate%20patate",
"patate%2520patate",
"patate&patate",
"patate& patate",
"patate = patate",
"patate ",
"patate/patate",
"patate!\"/$%?& *( ) _+^¨ >`:É. ',. é ;`^ ¸< nasty stuff here!")
.map(Arguments::of);
}
@SpringBootApplication
@EnableAutoConfiguration(exclude = { SecurityAutoConfiguration.class })
static class RequestEncodingTestApplication
{
public static void main(String[] args)
{
SpringApplication.run(RequestEncodingTestApplication.class, args);
}
@Component
static class UriComplianceCustomizer implements WebServerFactoryCustomizer<JettyServletWebServerFactory>
{
@Override
public void customize(JettyServletWebServerFactory factory)
{
factory.addServerCustomizers(this::customizeUriCompliance);
}
private void customizeUriCompliance(Server server)
{
for (Connector connector : server.getConnectors()) {
for (ConnectionFactory factory : connector.getConnectionFactories()) {
if (factory instanceof HttpConnectionFactory httpConnectionFactory) {
HttpConfiguration httpConfig = httpConnectionFactory.getHttpConfiguration();
httpConfig.setUriCompliance(UriCompliance.LEGACY);
}
}
}
}
}
@RestController
static class RequestEncodingTestController implements RequestEncodingApi
{
@Override
public String requestParameterGet(String parameter)
{
return parameter;
}
@Override
public String pathParameterDefaultGet()
{
return null;
}
@Override
public String pathParameterGet(String pathVariable)
{
return pathVariable;
}
@Override
public String requestParameterPost(String parameter)
{
return parameter;
}
@Override
public String pathParameterDefaultPost()
{
return null;
}
@Override
public String pathParameterPost(String pathVariable)
{
return pathVariable;
}
@Override
public String requestParameterPut(String parameter)
{
return parameter;
}
@Override
public String pathParameterDefaultPut()
{
return null;
}
@Override
public String pathParameterPut(String pathVariable)
{
return pathVariable;
}
}
@RequestMapping("/patate")
interface RequestEncodingApi
{
@GetMapping
String requestParameterGet(@RequestParam(required = false) String parameter);
@GetMapping("/frittte")
String pathParameterDefaultGet();
@GetMapping("/frittte/{pathVariable}")
String pathParameterGet(@PathVariable String pathVariable);
@PostMapping
String requestParameterPost(@RequestParam(required = false) String parameter);
@PostMapping("/frittte")
String pathParameterDefaultPost();
@PostMapping("/frittte/{pathVariable}")
String pathParameterPost(@PathVariable String pathVariable);
@PutMapping
String requestParameterPut(@RequestParam(required = false) String parameter);
@PutMapping("/frittte")
String pathParameterDefaultPut();
@PutMapping("/frittte/{pathVariable}")
String pathParameterPut(@PathVariable String pathVariable);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment