Serving Resources

Chapter 3: How to handle get requests to serve models and collections

The Hello World example showed how to serve a simple model. Let’s learn how it works.

Get requests

A get request1 from Resgate is similar to a HTTP GET request. It differs that it is sent over NATS instead of HTTP, and that the response must be a JSON object with a certain structure.

To listen for get requests, the service must subscribe to a subject with the pattern:

get.<resource>

Where resource is the the resource ID (as described as in previous chapter).

Listening for requests on the resource ID example.foo would look like this:

nats.subscribe('get.example.foo', (msg, reply) => { /* ... */ });

Tip

Wildcard subscriptions can be used for ID parameters:

nats.subscribe('get.inventory.item.*', (msg, reply, subject) => {
    /* Parse subject for the item ID */
});

The message data, msg, is a JSON object that may have the following property:

The response2 structure depends on if the response is a model, a collection, or an error.

Model response

If the resource is a model (same as in the Hello World example), the response should have the following structure:

{
	"result": {
		"model": { /* model data */ }
	}
}

And in code, it might look like this:

nats.subscribe('get.example.foo', (req, reply) => {
	nats.publish(reply, JSON.stringify({
		result: {
			model: { foo: "baz", bar: 42 }
		}
	}));
});

Collection response

If the resource is a collection, the response is slightly different:

{
	"result": {
		"collection": [ /* collection data */ ]
	}
}

And in code, it might look like this:

nats.subscribe('get.example.bar', (msg, reply) => {
	nats.publish(reply, JSON.stringify({
		result: {
			collection: [ 12, "bar", null ]
		}
	}));
});

Warning

Collections and models must not contain other collections or models. You are not allowed to send:

[
    { "id": 1, "name": "foo" },
    { "id": 2, "name": "bar" },
]

We explain how to solve nested/complex data structures in Chapter 8 - Nested resources.

Error response

In case of an error, most commonly Not Found or Internal Error, the response may look like this:

{
	"error": {
		"code": "system.notFound",
		"message": "Not Found"
	}
}

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

Access requests

Unlike with HTTP requests, access control is handled in a separate request called an access request4. This will be described more in detail in Chapter 7 - Access control.

To allow anyone to get our example resources, we can use a wildcard subscription that grants full access:

nats.subscribe('access.example.>', (msg, reply) => {
	nats.publish(reply, JSON.stringify({ result: { get: true, call: "*" }}));
});