Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

POST or GET in a search form?

I created a Search form to find posts on a MVC site.

Should the form type be POST or GET?

I know that being get is possible to bookmark the search and so on.

Any disadvantage of using GET?

Thank You, Miguel

like image 222
Miguel Moura Avatar asked Dec 12 '13 17:12

Miguel Moura


1 Answers

Even though GET is the more conventional solution for querying data, there are plenty of cases where a GET is too limited to perform a /search.

The essence of the problem, is that a GET has no request body, and for that reason it cannot handle more complex request. In essence a GET can only send data using the URL. A URL can contain path parameters and query parameters, which are just a set of key-value pairs where both key and value are of a string type.

By contrast, a POST can in addition also carry an entire JSON document in its body. By restricting ourselves to a GET, we cannot use any of those JSON features, and as a result we cannot send proper objects or arrays to our back-end.

How valuable are semantics, really ? Should we follow a workaround, which could result in technical debt, just to honor a naming convention?

An example of a problem case

As mentioned above, one of the possible problems, is that it cannot deal with arrays.

For instance, in a webshop, you want users to present with a catalog of products presented in a list. You want to offer your users the ability to select a number of vendors using checkboxes to filter the list. It would result in an array such as selectedVendors = ["vendorA", "vendorB"].

If we want to respect the convention of using a GET, then we have to find an acceptable workaround which allows us to send a list of vendors to the back-end without using a request body.

Workaround 1

With only query parameters at your disposal, it is possible to model it as a bunch of booleans: includeVendorA, includeVendorB, ...

Unfortunately, that's hard to maintain and difficult to document.

Workaround 2

The front-end could actually perform multiple queries. i.e.

  • Get the ones for vendorA first (/search?vendor=VendorA),
  • then the ones for vendorB (/search?vendor=VendorB)
  • then finally merge all results back together to a single list.

First of all, it has a performance penalty, because it needs multiple round-trips. But secondly, it also breaks the ability to support paging.

Workaround 3

Add incremental indexes to your query parameter names. (e.g. /search?vendor1=VendorA&vendor2=VendorB)

Again, hard to document, and not supported by OpenAPI neither.

Finally

If we can just accept that a POST is more suitable for a /search, then we don't need any of those workarounds.

Update 2021

Specifically for sending arrays over GET, there still isn't a standard yet. However, slowly frameworks and languages are shifting towards a de facto standard: /search?vendor[]=VendorA&vendor[]=VendorB.

One more specific shortcoming of the GET, would be the ability to model conditional filters: (e.g. in a ticket system: "give me all tickets which person X created and all tickets which person X closed", or in a webstore: "give me all products that are in discount and all products with free shipping"). They translate to database queries with a mix of AND and OR statements.

like image 66
bvdb Avatar answered Sep 21 '22 10:09

bvdb