Methods

Chapter 6: How to define and call methods on a resource

Each resource may have methods that can be called remotely through a call request1. It is in many ways similar to a HTTP POST request. Let’s have a look at it.

Call requests

To listen for call requests, the service subscribes to a subject with the following pattern:

call.<resource>.<method>

Where resource is the resource ID and method is the alphanumeric (no dots!) name you’ve given to the method.

In code, listening to calls to method mymethod on resource example.foo would look like this:

nats.subscribe('call.example.foo.mymethod', (msg, reply) => {
	/* Handle the request and send a response */
});

Request message

The call request’s message is a JSON object with the following properties:

  • params - method parameters as sent by the client
  • cid - connection ID string, generated by Resgate, and unique for every client connection
  • token - access token. Will be explained in Chapter 7 - Access control
  • query - optional query part of the resource ID explained in Advanced Topics - Query Resources

The message of a call request may look like this:

{
	"params": { "foo": "bar", "baz": 42 },
	"cid": "bhrq7ht8smgioj39ibr0",
	"token": null
}

Successful response

If the call is successful, the service sends a response2 with a JSON object with the following property:

  • result - result data as determined by the method. May be null.

In code it could look like this:

nats.subscribe('call.maths.utils.add', (msg, reply) => {
	let { params } = JSON.parse(msg);
	nats.publish(reply, JSON.stringify({
		result: params.a + params.b
	}));
});

Error response

In case of an error, such as Invalid parameters or Method not found, the response2 may look like this:

{
	"error": {
		"code": "system.invalidParams",
		"message": "Invalid parameters"
	}
}

Look at the pre-defined errors3 in the specification for a full list of error codes.

Tip

If you use a custom error, the first part of the error code should be the unique name of the service.
This will help in avoiding naming conflicts between multiple microservices.

Pre-defined methods

The RES protocol describes a few pre-defined call methods4 that may be used for specific purposes. Let’s go through them.

Set call request

A set request5 is used to update or delete a model’s properties. The subject has the method set:

call.<resource>.set

The parameters should be a JSON object where each property being the new value to set on the model. If a model property is to be deleted, a delete action6 should be sent by the client instead of a new or null value.

In case some model properties were changed, a model change event7 must be sent as described in Chapter 4 - Model Events. You must make sure the event is sent before the call response.

The response itself is the same as for custom call requests, described earlier in this chapter.

Tip

In case a different parameter structure is required, eg. for a compare-and-swap kind of update, it is recommended to create a custom method to handle that request.

By keeping the set parameters standardized, it is easier to create clients with generic CRUD operations.

New call request

A new request8 is used to create new resources. The subject has the method new:

call.<resource>.new

For new models, the parameters should be a JSON object containing the named properties and values of the new model.
For new collections, the parameters should be an ordered array containing the values of the new collection.

But more importantly, the success result must be a resource reference9 to the newly created resource.

A successful response may look like this:

{
	"result": {
		"rid": "example.item.42"
	}
}