10

Help me settle an internal question.

We have an endpoint which we all agree should be a GET, because all it's doing is calling a stored proc and returning a set of data. However, there is a set of filters that we need to pass to the endpoint. Below is an example of what the filers might look like if all of the filter options are passed:

{
    "DistributorCode":"6065",
    "Model":"123-xyz",
    "Serial":"654654065",
    "CurrentSMR":"11350.47",
    "SoldbyDistributor":"",
    "ServiceDistributor":"",
    "LatestSMRDate":"02/12/2020",
    "Coverage":"",
    "Customer":"",
    "CoverageExpirayDate":"",
    "SortBy":{
        "name" :"serial",
        "order":"asc"
    },
    "select":["eh","wt","fc"]
} 

We could just pass in this json string as a querystring parameter in the GET call, or we could have each of them be their own parameter (although SortBy might get tricky).

But some are concerned that this will make the URL too long, and we will risk running into max query string length errors. So, they want to make the call a POST instead. If it were a POST call, then it would require both an object in the body and at least one QS param (&code=) which is non-negotiable (it must be there.)

So we have two options (that I can think of):

  1. Make it a GET call with a potentially very long URL due to the parameters.

    1a) each filter is its own parameter

    1b) the list of filters is a json string in it's own parameter

  2. Make it a POST call that requires both QS parameters and a json object in the Body

Which would you do, and why?

Thanks!

  • @JonRaynor, thanks but I'm not sure how that applies to my question here. That questions is: Can I pass a body with a GET call. That's not what I am asking here. – Casey Crookston Feb 17 at 16:41
  • 1
    If your search parameters can't be accommodated via a query string, go with a post. I can't predict what the future needs of your application will be. Certainly a POST will be able to handle more information than a query string. – Jon Raynor Feb 17 at 16:47
  • @JonRaynor, thanks. After googling the correct thing, I finally found this: stackoverflow.com/questions/14202257/… which pretty much says what you said. It's okay to use POST in a case like this. – Casey Crookston Feb 17 at 16:49
  • 2
    As per stackoverflow.com/questions/417142/… you have 2000 characters for the whole URL. Subtract about 100 for the domainname, path, etc. and there is still plenty of space left for your entire question. – Jory Geerts Feb 17 at 16:50
8

Just do a GET with normal parameters. You are nowhere near the limit. You may want to make a little helper function that can take an arbitrary object and turn it into a query string.

The problem with 1b it is hard to debug (just changing a parameter in your web debugger becomes a chore). Also logs will be obscured. You lose out on the ability to filter access log for all instances where parameterx=Y etc.

The problem with 2 is you miss out on handy features like caching etc.

Also GET with body is a horrible hack. Don't do that

Also regarding the array in your example. Query strings support the same parameter multiple times so you can do ?select=eh&select=wt&select=fc

| improve this answer | |
  • 2
    Thanks! Also GET with body is a horrible hack. Don't do that < That was never on the table as an option :) – Casey Crookston Feb 17 at 17:12
  • 1
    I would also recommend not passing fields with no values. Your example body shows a number of fields with values of "". I'm assuming you don't want to only see e.g. records where the "Customer" is blank. You should just send parameters for fields that you are not part of the filter. – JimmyJames Feb 17 at 17:24
  • @JimmyJames, yes, you are correct. I just copied and pasted an example showing all possible values. – Casey Crookston Feb 17 at 18:59
  • 3
    @CaseyCrookston One other small recommendation: use ISO-style dates e.g. 2020-02-12. – JimmyJames Feb 17 at 20:13
2

Just do a POST with a body. You have an unbounded array "select":["eh","wt","fc"] which is going to be a pain to serialise as query string parameters and can possibly exceed the URL length restriction.

I would also recommend scrapping your sproc, having a simpler method that returned more objects and moving the filtering to the client.

This will take load off the database and make for a faster UI

Also spell check CoverageExpirayDate

| improve this answer | |
  • 1
    moving the filtering to the client.... This will take load off the database and make for a faster UI Except for very tiny tables, that is rarely going to be the case. Server side filtering, with appropriate indexes are going to beat client side filtering in the majority of cases. – Lie Ryan Feb 18 at 13:15
  • sorry thats just not true. client side is inherently more scale-able and in this case the OP is passing sort parameters for example – Ewan Feb 18 at 13:17
  • letting the client download 100MB of data so it can display 10 rows is a very inefficient use of database resources. Your database isn't going to scale that way. – Lie Ryan Feb 18 at 13:18
  • its ineffecient use of bandwidth, its super effecient use of database – Ewan Feb 18 at 14:04
  • Serializing millions of rows that ends up never being used is not a "super efficient use of database". – Lie Ryan Feb 18 at 15:04
2

In this case, often both possibilities are used:

  • Create a GET endpoint passing your query conditions in the query string (like suggestion 1a). You can also pass sort parameters easily in the query string.

You should only pass query parameters that are not empty or which are different from default values.

  • If you think that the query string may get too long (even though there is no specification limit, servers will usually have a limit), you can create a POST endpoint. You then pass the query and sort conditions in the body, preferably using JSON format.

In your example, the query string should not get too long. So here the GET endpoint is enough.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.