UNPKG

urban-airship-connect

Version:

node client for Airship's Real Time Data Streaming

144 lines (113 loc) 2.96 kB
var zlib = require('zlib') var https = require('https') var http = require('http') var url = require('url') var through = require('through2').obj var split = require('split2') var extend = require('xtend') var HEADERS = { Accept: 'application/vnd.urbanairship+x-ndjson;version=3;', 'Content-Type': 'application/json', } var CONNECT_URL = 'https://connect.urbanairship.com/api/events/' module.exports = connect function connect(appKey, accessToken, _opts) { var opts = _opts || {} var stream = through(write, end) var headers = extend(HEADERS, {}) var apiUrl = url.parse(opts.uri || CONNECT_URL) var parser = opts.parser || JSON.parse.bind(JSON) var protocol = apiUrl.protocol === 'https:' ? https : http var ended = false var filter = null var request = null var currentOffset = null var responseStream = null return stream function startRequest() { var connectFilter = extend(filter, {}) if (currentOffset) { connectFilter.resume_offset = currentOffset } stream.emit('connect') request = protocol.request( extend(apiUrl, { method: 'POST', headers: extend(headers, createConnectHeaders(connectFilter)), ecdhCurve: 'auto', }), gotResponse ) request.on('error', emitError) request.write(JSON.stringify(connectFilter)) } function createConnectHeaders(body) { return { 'Content-Length': JSON.stringify(body).length, 'X-UA-Appkey': appKey, Authorization: 'Bearer ' + accessToken, } } function checkReconnect() { if (!ended) { startRequest() } } function gotResponse(response) { if (response.statusCode === 307 && response.headers['set-cookie']) { stream.emit('redirect') headers.Cookie = response.headers['set-cookie'][0] checkReconnect() return } if (response.statusCode !== 200) { stream.emit( 'error', new Error(response.statusCode + ': ' + response.statusMessage) ) return } responseStream = response response .pipe(zlib.createGunzip()) .on('error', emitError) .pipe(split(parseJSON)) .on('error', emitError) .on('data', emitData) .on('end', checkReconnect) } function parseJSON(data) { if (!data) { return } try { return parser(data) } catch (err) { err.blob = data emitError(err) } } function emitData(data) { currentOffset = data.offset stream.push(data) } function write(data, _, next) { filter = data currentOffset = null if (request) { request.end() } startRequest() next() } function end() { ended = true if (request) request.destroy() if (responseStream) responseStream.destroy() } function emitError(err) { // if the stream is ending, we can just swallow any errors if (ended) return stream.emit('error', err) } }