springspring-bootrestcurlx-www-form-urlencoded

x-www-form-urlencoded Array inconsistently populated in Spring REST call


I am attempting to send a PUT request to a Rest API using x-www-form-urlencoded content. My aim is to send a list of strings in the request similar to this article. I have the following REST controller defined in a Spring Boot application to allow for this:

@RestController
@RequestMapping(value = "/rest/api", produces = MediaType.APPLICATION_JSON_VALUE)
public class RestApiController {

    @PutMapping(value = "/{id}", consumes = MediaType.APPLICATION_JSON_VALUE)
    private ReturnType putRestApiTypeJson(
        @PathVariable("id") String id,
        @ModelAttribute PutDataRequest request) {
    
        System.out.println();
        return null;
        
    }

    @PutMapping(value = "/{id}", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    private ReturnType putRestApiTypeUrlEncoded(
        @PathVariable("id") String id,
        @ModelAttribute PutDataRequest request) {
    
        System.out.println();
        return null;
        
    }
}

which leverages PutDataRequest defined by:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class PutDataRequest {

    Set<String> characters = new HashMap<>();
    Set<String> movies = new HashMap<>();

}

I try hitting the rest api controller via curl to perform testing. The Application JSON PUT request receives characters and movies no problem, however the form-urlencoded endpoint does so inconsistently:

// No data populated in PutDataRequest at debug time: curl -X PUT 'http://localhost:some-port/rest/api' -d 'characters=Some%20Name%26movies=Some%20Title' -H 'Content-Type: application/x-www-form-urlencoded'

// Data populated in PutDataRequest at debug time: curl -X PUT 'http://localhost:some-port/rest/api?characters=Some%20Name%26movies=Some%20Title' -H 'Content-Type: application/x-www-form-urlencoded'

Can anyone give an insight on why providing the key-value pairs via -d prevents the data from being forwarded to the form-urlencoded PUT endpoint? For context, I run this coded using spring version 5.2.3.RELEASE and spring boot version 2.2.4.RELEASE.


Solution

  • Also found another way to get around this error. Turns out PUT and DELETE requests aren't enabled by default, and you need to add an implementation for the formContentFilter method in your Application.java (or wherever you call SpringApplication.run(...) )

    Once I added the following to Application.java, I ran again and it worked like magic:

    @Bean
    @ConditionalOnMissingBean(org.springframework.web.filter.FormContentFilter.class)
    @ConditionalOnProperty(prefix="spring.mvc.formcontent.filter", name="enabled", matchIfMissing=true)
    public OrderedFormContentFilter formContentFilter() {
        return new OrderedFormContentFilter();
    }