3

This was very often in the past center of discussion, whether to use GET or POST for searchin.

If you are making for example geospatial request, both values are needed (lat and long). If you do it with GET, you cannot really annotate in openapi that both fields should be dependent on each other - the whole group lat/lon/distance required if one of them set. However there are some opened tickets that could solve these use cases by defining so called fragments, but I dont believe it will be standardized in OpenAPI anytime soon.

Is it really a bad thing to use POST in such cases? From my understanding, POST is used when data is mutated, however it gives us:

  • ++ ability to do validate very soon, if all parameters of specific search request are valid and not in controller/service layer
  • ++ makes URI more readable (can be used with along filtering)
  • -- not able to save it in bookmarks
  • -- for testing you need Postman/curl/...

So basically I would have something like this:

POST /stores?country=US
{
    "nearLocation": { "lat": 10, "lon": 10, "radius": "10km" }
}

instead of

GET /stores?country=US&lat=10&lon=10&radius=10km

which would require to validate the fields in controller and could not be defined in the openapi file.

What do you think, is it really a bad practice to move some fields to POST? I think we should differentiate between filtering and searching. You can filter enums, strings etc. and you can search with geospatial requests, date range requests where the comparator is not just equal. Am I thinking right?

Mejmo
  • 151
  • 4
  • Get will accept a form body. Additionally why not `/stores/us/(10,10)+10km` – Kain0_0 Mar 25 '20 at 05:45
  • Or a more URL friendly format like MGRS or UTM for urls: /stores/us/15SUD5505229951,10km – Berin Loritsch Mar 25 '20 at 20:24
  • Related: [What is the correct way to pass JSON objects in an http request when a GET request is most appropriate?](https://softwareengineering.stackexchange.com/questions/315544) – sleske Aug 14 '23 at 12:21

1 Answers1

2

Let me say that they can both be used for this purpose. As the complexity of your request goes up, the more you need a body instead of a parameter list on the URL. We can better define your example.

A couple critiques:

  • With coordinates, country is superfluous. It can be discovered by testing the point against the country polygons
  • What happens if the country is specified as UK, but the coordinates are for US? Do you return no results because the combination is not valid or return the results for the coordinate?

First, making use of well defined standards like GeoJSON helps your application integrate out of the box with many tools. For example your search could look like this:

POST /stores/search
{
  "radius": 10km,
  "location": {
    "type": "Point",
    "coordinates": [125.6, 10.1]
  }
}

That translates more directly to a GET URL like the following (parameter names are same as JSON object):

GET /stores/search?radius=10km&location=[125.6,10.1]

But you could also encode the URL so it is all part of the request and use fancy routing to convert it into parameters you are using. An example would be something that looks like this:

GET /stores/geosearch/[125.6,10.1](10km)

You'll also noticed that I added an action endpoint there for search or geosearch as opposed to the root /stores URL since by REST conventions that is where you would upload new records.

As to GET or POST, you have trade-offs:

  • Some proxies are set up to prevent POST or any other modifying verb in an effort to avoid spilling proprietary data. It's a lot less common now, but for very conservative entities it can be a thing.
  • GET is technically more correct since you are not modifying data, but...
  • As you have more and more parameters and the complexity of your search criteria goes up, you must switch to POST at a certain point. Many servers have URL length limitations.
Berin Loritsch
  • 45,784
  • 7
  • 87
  • 160
  • I think after three years it is very good time to accept this answer. It got just better and better after so much time. – Mejmo Aug 24 '23 at 15:31