UNPKG

reactive-superglue

Version:

Stream-based middleware for I/O integration of sources and sinks

198 lines (176 loc) 5.69 kB
var _ = require("highland") var http = require("http") var https = require("https") var proto = _().constructor.prototype var url = require("url") var express = require("express") module.exports = _ //cases: //_.http(req, res) //=>infers type. Pasando //_.http("http://www.google.es") //=> parses and infers type, returning the appropriate stream //some_stream().post("some url", "text/csv") //converts and sends a continuous post stream //_.ingest("route, defaults to /", optional_express_app) //infers the incoming data and passes a formatted stream // //some_stream().post("some url", "ndjson") //stringifies and sends a continuous post stream //some_stream().post("some url", "text/plain") //sends a continuous post stream _.http_duplex=function(u, method){ var dir=url.parse(u) dir.method=method return _(function(push, next){ var p = u.indexOf("https://") > -1 ? https : http var req=p.request(dir, function(res){ var duplex={req: req, res: infer_type(res)} push(null, duplex) }) }) } _.http = function (u) { return _(function (push, next) { var p = u.indexOf("https://") > -1 ? https : http console.log("GET ", u) var req = p.get(u, (res)=> { console.log("RES", u) if (!res.headers["content-type"]) var type = undefined; else var type = res.headers["content-type"].split(";")[0] push(null, infer_type(type, res)); push(null, _.nil) }) }).flatten() } _.http.get = function (u) { return _.http(u) } _.http.server = server function server(app) { if (!(this instanceof server)) return new server(app) this.app = app || express() if (!app) this.app.listen(3000) console.log("server started") } server.prototype.serve = function (route, stream) { if (!route) route = "/" else if (typeof route !== "string") stream = route var self = this; if (!stream) return { from: function (str) { return self.serve(route, str) } } var serve_fn = function (req, res) { console.log("processing request - GET ", route) var input = stream(req, res); var str = _(input).json().pipe(res); str.on("error", (err)=> { console.log("err", err.message) res.end(); }) } this.app.get(route, serve_fn) console.log("Route registered - serve", route) } server.prototype.duplex = function (route, responseReaderFn, requestWriterFn) { var streamFrom = responseReaderFn var streamInto = requestWriterFn if (!route) route = "/" else if (typeof route !== "string") responseReaderFn = route var self = this; if (!responseReaderFn) return { from: function (strO) { if (!requestWriterFn) { return { into: function (strI) { self.serve(route, strO, strI) } } } else return self.serve(route, str0, requestWriterFn) } } if (!requestWriterFn) { return { into: function (strI) { self.serve(route, responseReaderFn, strI) } } } var duplex_fn = function (req, res) { console.log("processing request - GET ", route) var inputWriter = requestWriterFn(req, res); var outputReader = responseReaderFn(req, res); _(req).pipe(inputWriter) outputReader.pipe(res); } this.app.all(route, duplex_fn) console.log("Route registered - duplex", route) } server.prototype.receive = function (route, stream) { if (!route) route = "/" else if (typeof route !== "string") stream = route var self = this; if (!stream) return { into: function (str) { return self.receive(route, str) } } var rcv_fn = function (req, res) { console.log("POST ", route) var input = _(req); var output = stream(req) var str = input.pipe(output) if (output.done) output.done(()=>{ res.end() }) else { req.on("end", ()=> { console.log("end req") res.end() }) } str.on("error", (err)=> { console.log("error", err) res.end(500) }) } this.app.put(route, rcv_fn) this.app.post(route, rcv_fn) console.log("Route registered - receive", route) } function infer_type(type, res) { switch (type) { case "application/json": res.setEncoding("utf-8") var lines = "" var result = _(res).split().scan("", (prev, line) => { try { lines += line if (!line.trim().endsWith("}") && !line.trim().endsWith("]")) { //to speed it up a bit return null; } var result = JSON.parse(lines); lines = "" return result } catch (err) { console.log(err) return null; } }).compact() return result; break; default: return _(res) } } proto.post = function (u) { var res_str = _() var opts = url.parse(u) opts.method = "POST" var req = http.request(opts, function (res) { console.log("received res for", u, res.statusCode) res.pipe(res_str) }) req.on("error", function (err) { throw err }) //var str=this.pipe(req) var str = this.pipe(req); return res_str }