Hello, World!

This is how a traditional node.js solution for “Hello, World!” might look like:

createServer ( ( req , res ) => res . end ( 'Hello, World!' ) ). listen ( 3000 );

In summary: request dispatching is defined using a function that takes a request and a response. This function has no meaningful return value. There’s no notion of the function being “done” processing the request, other than the call to .end . This forced many node developers to rely on hacks like patching .end for things as fundamental as logging response codes.

Quinn makes one small but important tweak to this model: Instead of taking the response as a second argument, the dispatch function is expected to return the response:

createServer ( createApp ( req => respond ({ body : 'Hello World!' })) ). listen ( 3000 );

This gains us a couple of helpful properties. The moment the function returns, both the status code and all headers are known. They can safely be written to the wire or a log file because it is impossible for anybody to change them from there on. Errors during request handling can bubble up naturally and be attributed to a request without the need to track continuation contexts or resorting to best effort guesses.

Another convenient consequence is that dispatch functions suddenly compose quite nicely and there’s no need for special middleware mechanics anymore. A “middleware” for Quinn can be as simple as this:

function requestLogger ( next ) { return async req => { console . log ( '<- %s %s' , req . method , req . url ); const res = await next ( req ); console . log ( '-> %s %s' , res . statusCode , req . url ); return res ; }; }

And using it in the app from above is as easy as calling a function:

createServer ( createApp ( requestLogger ( req => respond ({ body : 'Hello World!' })) ) ). listen ( 3000 );

Since there’s nothing more going on than functions calling other functions, there’s less need for libraries with “Quinn support”. You can just keep using lodash :

const middleware = [ requestLogger /*, ...more middleware */ ]; const initFramework = _ . compose ( createServer , createApp , ... middleware ); initFramework ( req => respond ({ body : 'Hello World!' })). listen ( 3000 );