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

Time:12-24

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 Name&movies=Some Title' -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 Name&movies=Some Title' -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.

CodePudding user response:

I decided to sidestep Spring in this situation. Instead of relying on Spring to figure out how to marshal the data I wanted, I added a HttpServletRequest to the form-urlencoded method signature and pulled the data out of the request:

@PutMapping(value = "/{id}", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
private ReturnType putRestApiTypeUrlEncoded(
    @PathVariable("id") String id,
    @ModelAttribute PutDataRequest data,
    HttpServletRequest request) {

String body = request.getRequest().lines()
    .map(line -> URLDecoder.decode(line, Charset.defaultCharset()))
    .collect(Collectors.joining(System.lineSeparator()));

// manipulate body content to extract desired data
    
}

I was inspired to do the above by this answer.

CodePudding user response:

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();
}
  • Related