0

I'm trying to pass a list of the following objects as query params to a GET call to my Java service:

{
    "id": "123456",
    "country": "US",
    "locale": "en_us"
}

As a url, this would like like

GET endpoint.com/entity?id1=123456&country1=US&locale1=en_us&id2=...

What's the best way to handle this as a service? If I'm passing potentially 15 of these objects, is there a concise way to take in these parameters and convert them to Java objects on the server side?

I imagine with a URL like this, the service controller would have a lot of @QueryParams...

xheyhenry
  • 1,049
  • 2
  • 13
  • 25
  • check this https://stackoverflow.com/questions/978061/http-get-with-request-body – Hussein Salman Mar 28 '18 at 00:15
  • @Coding The discussion on that post agrees that using a GET with a body is not a good idea, and to use a POST api instead. However, I specifically am trying to avoid using a POST API – xheyhenry Mar 28 '18 at 00:24

2 Answers2

2

Create the entire dataset as JSON array, e.g.

[
  {
    "id": "123456",
    "country": "US",
    "locale": "en_us"
  },
  {
    "id": "7890",
    "country": "UK",
    "locale": "en_gb"
 }
]

base64 encode it and pass it as a parameter, e.g.

GET endpoint.com/entity?set=BASE64_ENCODED_DATASET

then decode on the server and parse the JSON array into Java objects using perhaps Spring Boot.

Based on the valid URL size comment (although 2000 is usable), you could put the data in a header instead, which can be from 8-16kb depending on the server. GETting multiple resources at once is going to involve compromise somewhere in the design.

As Base64 can contain +/= you can url encode it too although I haven't found the need to do this in practice when using this technique in SAML.

Another approach would be to compromise on searching via country and locale specific IDs:

GET endpoint.com/entity/{country}/{locale}/{id_csv}

so you would search like this:

GET endpoint.com/entity/US/en_us/123456,0349,23421

your backend handles (if using Spring) as @PathParam for {country} and {locale} and it splits {id_csv} to get the list of IDs for that country/locale combination.

To get another country/locale search:

GET endpoint.com/entity/UK/en_gb/7890,234,123232

URLs are much smaller but you can't query the entire dataset in one go as you need to query based on country/locale each time.

codebrane
  • 4,290
  • 2
  • 18
  • 27
  • The problem with this approach is that the URL length can exceed the often used limit of 256 characters. Even the two items abovce encode to a Base64 string with 209 characters length. 15 such items will probably not work. –  Mar 28 '18 at 10:34
  • 1
    there's a de facto limit of 2000 chars in the URL https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers – codebrane Mar 28 '18 at 10:38
  • @codebrane Do you think this is better than just using POST? – xheyhenry Mar 28 '18 at 17:08
  • depends what the query is for @xheyhenry if it's to query multiple resources at the same time, then POST isn't suitable as it's for CREATE. If it's for creating new resources then POST should really be used but in the real world compromises sometimes have to be made and I think using base64 in the URL is fine. SAML uses base64 in the URL to send a SAMLRequest to an Identity Provider. It redirects the browser to the IdP with ?SAMLRequest=BASE64 via a GET request in order to get a 'resource' in this case a SAML Assertion. – codebrane Mar 28 '18 at 17:47
  • It's a search API and doesn't create any resources. At this point I just think a huge encoded url param is a hacky way to pass a json payload – xheyhenry Mar 28 '18 at 18:13
  • @codebrane also, don't you need to first BASE64 encode the JSON, then URL encode that result? – xheyhenry Mar 28 '18 at 18:25
  • Yes that's what I said in the answer, base 64 encode it. Generally I've never had the need to url encode base 64 but I've added a note in the answer for this – codebrane Mar 29 '18 at 08:03
  • I've updated the answer with another solution @xheyhenry where you can search using much smaller URLs – codebrane Mar 29 '18 at 08:16
0

It looks like your GET is getting multiple resources from the server. I'd consider refactoring to GET 1 resource from the server per GET request. If this causes performance issues, consider using HTTP caching.

saille
  • 9,014
  • 5
  • 45
  • 57