Skip to content

Instantly share code, notes, and snippets.

@trustmaster
Created July 28, 2014 08:15
Show Gist options
  • Save trustmaster/13ebe7e7eaed3c364311 to your computer and use it in GitHub Desktop.
Save trustmaster/13ebe7e7eaed3c364311 to your computer and use it in GitHub Desktop.
Router component interface example

Component description

Router is a static HTTP router mapping indexed HTTP patterns to indexed request outputs.

Inports

patterns inport is an addressable parameter accepting patterns the router handles, e.g.:

'get /hello' -> PATTERN[0] Router
'post /world' -> PATTERN[1] Router

filter inport is an optional parameter accepting custom middleware function applied to all routes in the router.

app inport accepts an application object and configures it with patterns and filters, mapping inputs and outputs. It's the primary port of the component.

Outports

req is an addressable output sending HTTP request objects to be processed down the stream, e.g.:

Router REQ[0] -> REQ Hello(myapp/HelloController)
Router REQ[1] -> REQ World(myapp/WorldController)

The problem

The component is triggered by the app port, which recieves a value from an upstream component on application start. By the moment app packet is received, all filter and pattern values must have already been received. If using NoFlo "as is", it is all screwed: first app packet arrived because it is triggered by an IIP in an upstream component, then pattern IIPs arrive, then filter arrives from another upstream component. And these events can be mixed in a different order.

For filter param I'm doing a nifty trick by utilizing component metadata:

AuthFilter FILTER -> FILTER Router(xpress/Router:filter=on)
component.inPorts.add 'filter',
  datatype: 'function'
  required: metadata and 'filter' of metadata and metadata.filter is 'on'

This makes WirePattern wait for filter to arrive before processing app.

But this trick cannot be applied to pattern, because it is an addressable port of arbitrary size accepting IIPs.

So, the problem is: how to ensure all pattern IIPs arrive before a value on app inport. And a related problem: how to ensure a specific order of IIPs in a graph.

exports.getComponent = (metadata) ->
component = new noflo.Component
component.description = "Static index-based router"
component.inPorts.add 'app',
datatype: 'object'
description: 'Express Application, triggers WirePattern'
required: true
component.inPorts.add 'patterns',
datatype: 'string'
description: "Request patterns as `verb /path`
or just `/path` meaning verb is `all`"
addressable: true
required: true
component.inPorts.add 'filter',
datatype: 'function'
description: 'Route filter middleware (omitted by default)'
required: metadata and 'filter' of metadata and metadata.filter is 'on'
component.outPorts.add 'req',
datatype: 'object'
description: 'Express Request objects (contain responses)'
addressable: true
required: true
component.outPorts.add 'error',
datatype: 'object'
required: false
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment