REST Webservices (post / put) : which type of parameter should I choose, and when

httphttp-requestparametersrest

On a POST (or PUT) webservice, I know can use three different type of parameters, I can send my parameters in the path of the URL /objects/{path_param}, after a question mark in the URL /objects?{param_name}={Param_value} or in the body of the request.

For GET webservices, I use path to identify a ressource, and query to add some filtering when the ressource is a list.

My main question is "When should I choose to use a path/query/body on a POST/PUT webservice?". Based on that, is it acceptable to have both query parameters and body parameters on the same webservice?

For now, the only difference between query and body parameters I know is that query parameters can be sent as part of the URL, and can therefore be cached or kept in the browser history, so I'd like to know the other differences that should be take into consideration.

Best Answer

REST API over HTTP 1.1

These are (summarising) the "principles" we should considerate if we want to be RESTful-compliant. Among many other things (see also CoRE RFC6690)

Path variables

These variables are used for referencing resources within a hierarchy. (independently of the Method)

GET: /app/{appId}/user/{userId} #single resource
GET: /app/{appId}/users #collection
POST: /app/{appId}/user/{userId}
DELETE: /app/{appId}/user/{userId}
...

Query variables

These variables are used as modifiers of the response. By modifiers we mean: filters, pagination, attribute selection,etc.

GET: /app/{appId}/users # all app users

Response modification:

  GET: /app/{appId}/users?name=Jhon&surname=Conor # Subset by filtering
  GET: /app/{appId}/users?page=1&pageSize=10 # Subset by pagination
  GET: /app/{appId}/users?page=1&pageSize=10&filter=name:jhon;surname:conor # Subset by pagination and filtering

AppId is still working for referencing. It gives the scope/context where to look at (users of the app X). Changing this value we are not modifying the response, we are switching the resource.

These variables could be used with PUT, POST, DELETE in order to perform these actions over a subset of resource, but in the words of the OP

I think the use case would be possible in theory but very rare in the practice.

(And I agreed)

Body variables

Being dogmatic, we use POST to create new resources, and PUT to modify an existing one.

Both of them require a request body, where the resource to create/update is represented in its final status.

Note: Here is important to make reference to their idempotent nature

POST: /app/{appId}/user
BODY: {"name":"Jhon", "surname":"Conor"}
PUT: /app/{appId}/user/{userId}
BODY: {"name":"Sara", "surname":"Conor"}

Again, appId and userId are mere referencing variables.

Summarizing

  • path variables: for referencing (resource navigation)
  • query variables: for response modifications
  • Body: for resource creation or modification.

Here the specifications: RFC7230 - RFC7235

SOA Webservices over HTTP 1.1

I have separated SOA WS from API RESTful because these are 2 different designs where each of them uses the mentioned Http variables in a different way.

These WS does not use URI for web resource referencing. They use them to expose procedures.

POST: /app/register
Body:  {"name":"Jhon", "pass":"Conor"}
POST: /app/sendNotification
Body:  {"from":"Jhon", "to":"skynet", text:"see you yesterday"}
POST: /app/markNotificationAsRead
Body:  {"id":"0"}
POST: /app/moveNotifications
Body:  {"from":"inbox", "to":"trash", messages:[]}
GET: /app/notifications?from=Jhon
GET: /app/notifications?if=from:Jhon;to:skynet

In this approaches, GET and POST are predominant.

Path and body variables are used as procedure arguments.

Query variables keep its function of response modificator.

The specs to implement depends on the needs of the system. As @Eric has pointed out, there are specs like RPC that can be applied to this sort of Webservices.