balena-cli/lib/resin/server/server.coffee

145 lines
3.4 KiB
CoffeeScript
Raw Normal View History

2014-11-18 13:59:19 +00:00
_ = require('lodash')
2014-10-31 15:59:23 +00:00
request = require('request')
progress = require('request-progress')
async = require('async')
2014-11-26 16:07:10 +00:00
connection = require('../../connection/connection')
settings = require('../settings')
2014-12-22 18:43:38 +00:00
auth = require('../auth/auth')
2014-10-31 15:59:23 +00:00
2014-12-08 12:48:39 +00:00
# @nodoc
urlResolve = require('url').resolve
# Send an HTTP request to resin.io
#
# @param {Object} options request options
# @option options {String} url relative url
# @option options {String} json request body
# @option options {String} method HTTP method
# @option options {Object} headers custom HTTP headers
# @option options {Function} pipe define this function if you want to stream the response
#
# @param {Function} callback callback(error, response, body)
# @param {Function} onProgress on progress callback(state) (optional)
#
# @note If the user is logged in, the token gets automatically added to Authorization header
# @note If the response is JSON, it will attempt to parse it
#
# @throw {Error} Will throw if you don't have internet connection
#
# @example GET request
# resin.server.request {
# method: 'GET'
# url: '/foobar'
# }, (error, response, body) ->
# throw error if error?
# console.log(body)
#
# @example POST request with body
# resin.server.request {
# method: 'POST'
# url: '/foobar'
# json:
# name: 'My FooBar'
# }, (error, response, body) ->
# throw error if error?
# assert(response.statusCode is 201)
#
# @example Stream download
# resin.server.request {
# method: 'GET'
# url: '/download'
# pipe: fs.createWriteStream('/tmp/download')
# }, (error) ->
# throw error if error?
# , (state) ->
# console.log("Received: #{state.received}")
# console.log("Total: #{state.total}")
# console.log("Is Complete? #{state.complete}")
#
2014-12-02 14:57:47 +00:00
exports.request = (options = {}, outerCallback, onProgress) ->
onProgress ?= _.noop
2014-11-18 13:59:19 +00:00
if not options.url?
throw new Error('Missing URL')
2014-10-31 15:59:23 +00:00
async.waterfall [
2014-10-31 15:59:23 +00:00
(callback) ->
connection.isOnline(callback)
(isOnline, callback) ->
if not isOnline
return callback(new Error('You need internet connection to perform this task'))
2014-12-22 18:43:38 +00:00
auth.getToken(callback)
(savedToken, callback) ->
2014-12-05 14:53:59 +00:00
options.url = urlResolve(settings.get('remoteUrl'), options.url)
2014-11-18 13:59:19 +00:00
if options.method?
options.method = options.method.toUpperCase()
_.defaults options,
method: 'GET'
2014-11-18 14:05:38 +00:00
gzip: true
2014-10-31 15:59:23 +00:00
if savedToken?
options.headers ?= {}
_.extend options.headers,
'Authorization': "Bearer #{savedToken}"
2014-10-31 15:59:23 +00:00
2014-12-02 14:57:47 +00:00
if options.pipe?
progress(request(options))
.on('progress', onProgress)
.on('error', outerCallback)
.on('end', onProgress)
.pipe(options.pipe)
.on('error', outerCallback)
.on('close', outerCallback)
else
return request(options, callback)
2014-10-31 15:59:23 +00:00
(response, body, callback) ->
try
response.body = JSON.parse(response.body)
2014-10-31 15:59:23 +00:00
if response?.statusCode >= 400
error = new Error(response.body)
2014-10-31 15:59:23 +00:00
return callback(error, response, response.body)
2014-10-31 15:59:23 +00:00
2014-12-02 14:57:47 +00:00
], outerCallback
2014-12-08 12:48:39 +00:00
# Generate shorthand functions for every method
#
# @private
#
# @todo Find a way to document all of the methods directly
#
2014-11-18 14:33:24 +00:00
createFacadeFunction = (method) ->
lowerCaseMethod = method.toLowerCase()
exports[lowerCaseMethod] = (url, body, callback, onProgress) ->
2014-11-18 14:33:24 +00:00
options = {
method
url
}
if _.isFunction(body)
onProgress = callback
2014-11-18 14:33:24 +00:00
callback = body
else
options.json = body
return exports.request(options, callback, onProgress)
2014-11-18 14:33:24 +00:00
for method in [
'GET'
'HEAD'
'POST'
'PATCH'
'PUT'
'DELETE'
]
createFacadeFunction(method)