2

Context:

I want to write an endpoint that will return a Collection of users based on their usernames. How should those username be passed to the REST endpoint - note that I can (potentially) have a lot of usernames (say > 5000)?

Solution #1:

Use a GET endpoint, concatenate the usernames on client side and pass them as a single request parameter. Split the request parameter on server side to get the list of usernames.

@RestController
public class UserController { 

    @GetMapping
    // able to deserialize `filename1,filename2` to List out of the box
    public Collection<User> getUser(@RequestParam List<String> usernames) {
        return userService.getUsersByUsername(usernames);
    }

}

Solution #2:

Use a POST endpoint and pass the list of usernames as request body. Although cleaner form a coding perspective, I end up using a POST to fetch data.

@RestController
public class UserController { 

    @PostMapping
    public Collection<User> getUser(@RequestBody List<String> usernames) {
        return userService.getUsersByUsername(usernames);
    }

}

Questions:

  1. Which of the two solutions would be the better approach?
  2. Do you have a better approach to pass the list of usernames into the endpoint?

Edits:

  • I've updated the signature of the first solution based on suggestions from answers. Spring is able to deserialize filename1,filename2 to List out of the box for @RequestParam.
Zoe
  • 27,060
  • 21
  • 118
  • 148
  • 1
    Given the amount of data as parameters, you'd better go with the `POST` solution. It will also be easier to test things with tools like postman. – Arnaud Oct 05 '18 at 07:34

4 Answers4

1

POST looks like a cleaner approach in this case because -

  1. Sending a huge string in a URL is not a good idea and there is scope for error
  2. You need to write additional code (logic) to create the string on frontend and split it on backend.
  3. Sending a huge string in a URL is not scalable as there are limits on the length of URL.
Rishikesh Dhokare
  • 3,559
  • 23
  • 34
0

Get approach might result into an issue since URL length is limited and then you have to limit your query parameters.

Though its not a post request but in your case i think post is the only way out.

saurav
  • 5,388
  • 10
  • 56
  • 101
0

GET is not limited, yet the browser is. Your server client does not seem to be the browser, so I would say GET is the way to go.

P.S GET can receive a body (not so great, but POST is not also the best match).

You don need to concatenated the string and add extra computation on server server, GET can receive a list of separate strings.

UPDATE with example:

@RestController
public class MyController {

    @GetMapping(value = "/test")
    public List<String> getTestParams(@RequestParam List<String> params) {
        return params;
    }
}    

The test with 3000 params

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class TestMyController {

    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    public void testRequestWithParamsList() {    
        List<String> params = new ArrayList<>();
        for (int i = 0; i < 3000; i++) {
            params.add(String.valueOf(i));
        }

        List<String> result = restTemplate.getForObject(buildUrl(params),
                List.class);

        assertEquals(params, result);
    }

    private String buildUrl(List<?> params) {
        return "/test?params=" + getUrlParameter(params);

    }

    private String getUrlParameter(List<?> params) {
        return params.stream()
                .map(Object::toString)
                .collect(Collectors.joining(","));
    }
}    

If you are using tomcat you must specify also the max http header property in application.properties

server.max-http-header-size=30000 
Adina Rolea
  • 2,031
  • 1
  • 7
  • 16
  • The GET request body can be tricky, see https://stackoverflow.com/questions/978061/http-get-with-request-body –  Oct 05 '18 at 08:36
  • Do you have a working snipped of receiving a List as `@RequestParam`? See https://pastebin.com/9aBZXqQ1 for some snippets. –  Oct 05 '18 at 08:37
  • Updated with example – Adina Rolea Oct 05 '18 at 12:52
0

I would agree with all the answers given above. I would like to specify one more point , if you are going with post request you might have to increase the payload capacity a server can receive , the default post capacity(The maximum size in bytes) of spring boot is 2mb (based on your server). While testing your code might work fine with 1000-2000 usernames but make sure to change the property to accept more bytes in request.