Case Study: An HTTP server - deanrad/rx-helper GitHub Wiki
How would you use Rx-Helper to build a server?
It may be sufficient to encode an HTTP request like /api/users?q=bob
as:
{
type: 'http/get',
payload: {
path: '/api/users',
query: { q: 'bob' }
}
} // FSA representation of /api/users?q=bob
But you'd quickly run into trouble. When rendering that response, how does the server know which response
object to call res.write
on? How do we give the correct, live response
object to the Handler that is receiving the event object?
The answer lies in the context
parameter you can give when processing or trigger-ing an event:
A vanilla express application would look like:
app.get("*", function(request, response) {
const { path, query } = request
response.json({ path, query })
})
In other case studies with Rx-Helper, we saw code that creates an FSA, populates it, and hands it off to agent.process
, like this:
agent.process(event)
But now, let's include a little more context, as we give the agent its item to process:
app.get("*", function(request, response) {
const type = "http/" + req.method.toLowerCase()
const event = { type, payload }
// Provide the response object in the 2nd parameter 'context'
agent.process(event, { response })
})
As before, we populate a Flux Standard Action object with whatever fields we care about from the request.
Then we pass it, and an object with a single field "response", containing the Express response
. Finally, in a renderer, which you'll recall is a function responsible for fulfilling an FSA, we'll be able to ask for the event AND the context:
agent.on("http/get", ({ event, context }) => {
const { query, path } = event.payload
// Get our response object from the context
const { response } = context
if (path.includes("api")) {
response.json({ path, query })
}
})
Decoupling - Why?
You may wonder what this buys us, this separation of the request definition and the response fulfillment.
The main benefit comes from the fact that now there is a single object, the event stream, representing ALL requests that come into the website. You can now use all the querying tools that RxJS provides for Observables in order to do things like rate-limiting that weren't feasible to do with conventional express code. Questions that involve the correlation between requests like these become easier to answer:
- What requests were also being processed during this one?
- Can we rate-limit by country?
Demo
Clone the rx-helper repo, and its main startup script will run the server in the file demos/express
git clone https://github.com/deanius/rx-helper
cd rx-helper && npm install && npm start
http://localhost:3120