Restspace services

Introduction

A Restspace service is a code module which acts as a function, taking an HTTP message as input and returning an HTTP message as output. A Restspace service is configured on a Restspace server (or serverless function) in a services.json file which specifies the base path to the service from the server's domain as well as authorisation rules to determine who can access the service.

Restspace services are stateless which means they do not themselves manage data and so have no lifecycle. They will however frequently manage access to data. In this case they will use an adaptor to do this. An adaptor is a plugin driver that gives access to external services.

An important feature of Restspace is that it imposes standard interfaces on commonly used services with this model. For instance, the JSON Service embodies the Restspace API for dealing with JSON data. The JSON Service can be configured with different adaptors to implement this API as local file-based storage, S3 bucket storage, (and in the future) Mongo Db storage or relational Db storage.

Details

Restspace services talk to each other using HTTP, whether or not they are on the same server. On the same server web requests are replaced by requests on an internal bus which have near zero overhead. Restspace can be built across several servers with services distributed as seems best. For more on this see Architecture.

Restspace services are configured with a block of JSON in services.json. All services share a set of configuration parameters which are described in Service configuration. They add to these parameters more configuration specific to the service.

Certain conventions are observed by Restspace services in how they work with HTTP. Internally and externally request bodies will contain 3 kinds of payload: data, in the form of JSON; text; or streamed binary data. Restspace services which work with data always assume data is in the form of JSON. Any kind of text or binary payload is allowed. In addition the following rules are observed:

  • OPTIONS requests take no actions and always succeed independent of the permissions on the service.
  • HEAD requests are supported: internally they are just GET requests where the server does not send the body, so they may entail work by the server but will require less bandwidth to receive.
  • Responses from services will contain a header X-Restspace-Service which contains the name (from services.json) of the service which handled the request.

Service API style

/email/send/<email template>/<recipient(s)>

/send-email

Services tend to 'spread' their functionality across the paths they control, using path elements like arguments to a function as much as possible. This is in contrast to the API structuring style which commonly happens with REST interfaces where specific urls represent a function and the request body is used to carry the data and parameters required.

As an example the email service uses a url pattern: /email/send/<email template>/<recipient(s)>. In this, /email is the base path for the email nanoservice, /send is the function and then the next two elements specify the template and the recipients.

A more common API pattern for a function like this would simply be /send-email with the body carrying the other data.

Restspace prefers the former because it allows parameters to be passed between services by url transformations. See Url patterns for how this works. Also it moves closer to the intent of HTTP that url paths would map to 'resources' which could be directly worked on via HTTP requests.