Skip to content

Adstream.data backend node

MaxMotovilov edited this page Jan 21, 2012 · 1 revision

Backend API Reference: Node.js

App.configure()

Called once during instantiation of the service endpoint (i.e. adstream_data()). Establishes the routing to the individual handlers by calling methods get(), update(), create() and del() on its argument. At this time, only get() is implemented:

arg .get( rel\_url, handler, depth )

  1. Associates user-defined method handler with get operation on the schema object determined by the pattern in rel\_url, or
  2. Marks the schema object pointed to by rel\_url as not supporting the get operation (if handler is omitted).

HTTP GETs are processed by recursively collecting and calling the user-supplied get handlers, starting at the URL the GET request was directed to. The order in which the handlers are executed depends on the URL patterns passed into get() which are described below. If a schema object is marked as not supporting get, the process stops at it — its descendants may still be accessed by GETs directed to their respective URLs.

The third, optional, argument depth may be used to indicate that the handler will be supplying not just the schema object it is associated with but also depth layers of its descendants. In this case, get handlers associated with those descendant objects will not be invoked and the recursive process will resume below them in the hierarchy.

URL patterns, key and item objects

The URL patterns should always contain substitution placeholders in positions corresponding to the IDs of items within containers. There are two types of substitution placeholders:

  1. Fixed: “:placeholder\_name
  2. Variable: “\*” (for get and del handlers) or “\*placeholder_name” (for create and update handlers).

Fixed placeholders are bound to specific values once per a call to handler. They are passed into the handler as named properties of its key argument. The handler may be called multiple times in the course of processing a single request with fixed placeholders bound to different values.

Variable placeholders are used to imply the values that will be filled in by the handler and/or to allow the handler to process the corresponding objects from the request body in one batch.

Fixed placeholders must precede any variable placeholders in any URL pattern. The sequence of fixed placeholders in a URL pattern constitutes its fixed prefix which determines the order in which the handlers are executed:

Order of calls to handlers

All handlers with fixed prefixes of identical length execute in parallel (i.e. they are activated together in unspecified order and the process does not continue until all of them complete). Groups of handlers with identical fixed prefix length execute in the order of their lengths: earlier handlers are expected to populate the response object with sufficient data so that longer fixed prefixes can be bound using the corresponding IDs from the response.

key object

All handlers receive an object of this type as their first argument. Conceptually, the key corresponds to the URL pattern associated with the handler with its fixed placeholders already bound. The values of the fixed placeholders are available as named properties on the key object.

key.url()

key.url( args… )

This method binds zero or more of the variable placeholders in the pattern and returns the resulting URL. If the number of arguments passed into the call is fewer than the number of the variable placeholders, the URL is cut off at the first non-bound placeholders. Note that fixed placeholders are pre-bound and should not be supplied as arguments for the url() call.

item object

All handlers other than get receive an object of this type — or an array of such objects, if they have at least one variable placeholder in their URL pattern — as their second argument. An item object encapsulates the values of the variable placeholders — available as its named properties — along with the corresponding object from the request body and its exact URL.

item.url()

item.url( args… )

Returns URL of the object from the request body held by item. As in key.url(), arguments can be used to bind variable placeholders in the URL pattern. The difference is that in item they are pre-bound to begin with and supplying arguments to this method re-binds last N placeholders leaving others alone. This is normally used to replace temporary IDs in create handlers with the real ones.

item.data()

item.data()

Returns the object from the request body held by item.

item.copy()

Returns a shallow copy of the object from the request body that will not include any known children, only the properties. The metadata property (\_) is also shallow-copied. If the item has temporary ID (@<<_ID_>>), the replaces metadata property is automatically injected into the copy.

App instances

The constructor function passed into the call to adstream_data() is used to create context objects for every HTTP request being processed. Two properties, request and response are automatically injected into the context objects after construction. All handler methods installed by App.configure() will be executed with this pointing to the appropriate context object.

Handler functions

All handler functions are called in the scope of the context object and can access this.request and this.response. A handler may return a non-promise value (which is ignored; using false as result is suggested) if it completes synchronously or a promise if it requires asynchronous processing.

get handlers

get\_ XXX : function( key )

create handlers

add\_ XXX : function( key, items )

The second argument is an array of item objects: the create handlers should always have at least one (usually exactly one) variable placeholder in the URL pattern.

The important thing about create handlers is the processing of the temporary item IDs (@<<_ID_>>) from the request. There will never be any temporary IDs in the key URL. Item URLs (and placeholders) will contain at least one temporary ID: the last of the variable placeholders. After the handler completes, all replaces metadata properties of the objects it inserts into the response body are automatically collected to map temporary IDs that’s been bound for other create handlers lower in the tree.

del handlers

del\_ XXX : function( key, item\or\items )

The second argument is either an item object or an array of such objects, depending on the presence of variable placeholders in the pattern. The value returned by item.data() could be null if the request does not specify version, or an empty object with the following metadata (_ property) structure:

{code}{
delete: true,
version: SomeValue
}
{code}

Note that del handlers are not collected from the tree recursively: only the handler at the URL designated in the request gets executed and not the handlers below it.

request

An object that can be used to access the query string arguments from the URL as well as the request body.

request.get()

this.request.get( rel\_url, metadata )

Returns the object at rel\_url from the request body (or undefined). If the metadata prototype is supplied, the object will be created if not already present and its _ property filled in with the combination of properties already present in the request body, query string arguments and the default values supplied in the prototype.

The metadata prototype is a one-to-two level dictionary corresponding to the adstream.data metadata structure. The properties with string, numeric, boolean or null values are considered leaves and are matched against the dictionary of arguments from the query string as follows:

  • null property in the prototype: matching query string argument is removed from the set and added as a string metadata property. If there’s no matching argument, nothing is added to metadata;
  • String property in the prototype: matching query string argument is removed from the set and added as a string metadata property. If there’s no matching argument, the value from the prototype is added to metadata;
  • Numeric property: matching query string argument is removed from the set and added as a numeric metadata property (non-numeric values cause an exception). If there’s no matching argument, the value from the prototype is added to metadata unless it is equal to NaN, in which case nothing happens;
  • Boolean property: matching query string argument is added as false if it is empty or equal to "0", "false", "n" or "no" (character case ignored), otherwise as true. If there’s no matching argument, the value from the prototype is added to metadata.

Note that if any metadata are successfully collected from the query string or the template, get() will always create the requested object within request and return it.

request.arg()

this.request.arg( name )

Removes specified argument from the query string and returns it; returns null if argument is not present. It is preferable to use metadata collection mechanism in get() instead in most cases.

response

An object that can be used to build the response body as well as signal errors.

response.set()

this.response.set( rel\_url, value, metadata )

Mixes in all properties from value into the response object at rel\_url, creating one if necessary. If metadata is passed in, also mixes in its content into the _ property of the object. Note that if you pass in the metadata as part of value_, it will overwrite the current content of @, if any, without mixing it. Method @set() returns the resulting response object so it can be directly modified by the user code if necessary.

response.fail()

this.response.fail( http\code, message, http\headers )
bq. this.response.fail( promise, http\
code, message, http\
headers )

Terminates the handler by throwing an exception (first form) or signaling an error via the promise object (second form); passes the resulting HTTP status code, descriptive message and (optionally) a dictionary of HTTP headers to be returned as part of response.