Driver and router component for manage HTTP/HTTPS services with Cycle.js
npm i cycle-node-http-serve --save
Create the driver
Arguments
configwith specifics optionsmiddlewares : Array: array of express compatible middlewares like serveStatic or bodyParserrender: (template) => template: a template engine renderer, call withreq.response.render(template)
const {run} = require('@cycle/run');
const {makeHttpServerDriver} = require('cycle-node-http-server');
function main(sources){
const {httpServer} = sources;
const sinks = {
}
return sinks;
}
const drivers = {
httpServer: makeHttpServerDriver()
}
run(main,drivers)To create a server instance, we need to send a config stream to the httpServer output. Like this :
const httpCreate$ = xs.of({
id: 'http',
action: 'create',
port: 1983
});
const sinks = {
httpServer: httpCreate$
}create action config:
id: the instance reference name. Needed to select the server stream on input.action:'create': the action nameport: see server.listen([port][, hostname][, backlog][, callback]) on NodeJS Apihostname: see server.listen([port][, hostname][, backlog][, callback]) on NodeJS Apibacklog: see server.listen([port][, hostname][, backlog][, callback]) on NodeJS Apihandle: see server.listen(handle[, callback]) on NodeJS Apipath: see server.listen(path[, callback]) on NodeJS Apisecured: set at true to create a HTTPS server.securedOptions: Needed ifsecuredistruesee Node HTTPS createServer optionsmiddlewares : Array: array of express compatible middlewares like serveStatic or bodyParser
Basic example with HTTPS
const securedOptions = {
key: fs.readFileSync(`${__dirname}/certs/key.pem`),
cert: fs.readFileSync(`${__dirname}/certs/cert.pem`)
};
const httpsCreate$ = xs.of({
id: 'https',
action: 'create',
port: 1984,
secured: true,
securedOptions
});To close a server instance we need to send a config stream to the httpServer output.
const httpClose$ = xs.of({
id: 'http',
action: 'close'
});
const sinks = {
httpServer: httpClose$
}create action config:
id: the instance reference name. Needed to select the server stream on input.action:'close': the action name
Select the server width this specific id
Return Object
const http = httpServer.select('http');Get event with name stream from a httpobject.
const http = httpServer.select('http');
const httpReady$ = http.events('ready');
const httpRequest$ = http.events('request');Return Stream
Dispatched when the server is ready to listen.
Returned values :
event:'ready'instanceId: The instance idinstance: the original Node.js server object
Dispatched when the server received a request.
See Request object above.
event:'request',instanceId: The instance idoriginal: original NodeJS request object,url: request's url,method: request's method (POST,GET,PUT, etc...),headers: request's headers,body: the body request.undefinedby default. See BodyParser middlewareresponse: the response object
Format response for driver output.
content: the body responseoptions:statusCode: default200headers: defaultnullstatusMessage: defaultnull
Return formatted object for driver output
Format response in json.
See send()
Format response in plain text.
See send()
Format response in html.
See send()
Format response with the render engine defined in makeHttpServerDriver() options.
Format response redirection for driver output.
path: path to redirectoptions:statusCode: default302headers: defaultnullstatusMessage: defaultnull
Return formatted object for driver output
const {run} = require('@cycle/run');
const {makeHttpServerDriver} = require('cycle-node-http-server');
function main(sources){
const {httpServer} = sources;
// get http source
const http = httpServer.select('http');
// get requests
const serverRequest$ = http.events('request');
const httpCreate$ = xs.of({
id: 'http',
action: 'create',
port: 1983
});
// response formated with a helper response object
// Response in text format : 'covfefe'
const response$ = serverRequest$.map( req => req.response.text('covfefe') );
const sinks = {
httpServer: xs.merge(httpCreate$,response$)
}
return sinks;
}
const drivers = {
httpServer: makeHttpServerDriver()
}
run(main,drivers)A Router component using switch-path
Arguments
Router(sources,routes)
sources: Cycle.js sources object with a specific sourcerequest$, a stream of http(s) requests.routes: a collection of routes. See switch-path
Return stream
const {makeHttpServerDriver, Router} = require('cycle-node-http-server');
function main(sources) {
const { httpServer } = sources;
// get http source
const http = httpServer.select('http');
// create the http server
const httpCreate$ = xs.of({
id: 'http',
action: 'create',
port: 1983,
});
// get requests
const serverRequest$ = http.events('request');
// routing
const router$ = Router({ request$: serverRequest$ }, {
'/': sources => Page(Object.assign({}, sources, { props$: xs.of({ desc: 'home' }) })),
'/user/:id': id => sources => Page(Object.assign({}, sources, { props$: xs.of({ desc: `user/${id}` }) })),
});
const sinks = {
httpServer: xs.merge(httpCreate$, router$.map(c => c.httpServer).flatten()),
};
return sinks;
}
function Page(sources) {
const { props$, request$ } = sources;
const sinks = {
httpServer: xs.combine(props$, request$).map(([props, req]) => req.response.text(props.desc))
}
return sinks;
}Here are discribed two usefull express middlewares.
It is used to serve static files ( images, css, etc... )
Basic usage
const serveStatic = require('serve-static');
const {makeHttpServerDriver} = require('cycle-node-http-server');
const drivers = {
httpServer: makeHttpServerDriver({middlewares:[serveStatic('./public')]})
}It is used to parse request body and return a full formated body.
Basic usage
const bodyParser = require('body-parser');
const {makeHttpServerDriver} = require('cycle-node-http-server');
const drivers = {
httpServer: makeHttpServerDriver({
middlewares: [
// two parsers used to format body POST request in json
bodyParser.urlencoded({ extended: true }),
bodyParser.json()
]
})
}Using Snabbdom
Snabbdom is the Virtual DOM using by @cycle/dom. It's possible to use it in server side with snabbdom-to-html.
A small helper to use snabbdom with cycle-node-http-server
const snabbdomInit = require('snabbdom-to-html/init');
const snabbdomModules = require('snabbdom-to-html/modules');
const {makeHttpServerDriver} = require('cycle-node-http-server');
export default function vdom(modules=[
snabbdomModules.class,
snabbdomModules.props,
snabbdomModules.attributes,
snabbdomModules.style
]){
return snabbdomInit(modules);
}
const drivers = {
httpServer: makeHttpServerDriver({
render: vdom()
})
}In main function, snabbdom used with JSX
const response$ = request$.map( req => req.response.render(
<div>
Pouet
</div>
))MIT