UNPKG

4.46 kBtext/coffeescriptView Raw
1dns = require 'http-dns'
2qs = require 'qs'
3superagent = require 'superagent'
4url = require 'url'
5
6_ = {
7 defaults: require 'lodash/defaults'
8 dropRight: require 'lodash/dropRight'
9 each: require 'lodash/each'
10 isEmpty: require 'lodash/isEmpty'
11 join: require 'lodash/join'
12 minBy: require 'lodash/minBy'
13 pick: require 'lodash/pick'
14 split: require 'lodash/split'
15 takeRight: require 'lodash/takeRight'
16}
17
18discardReturn = require './discard-return.coffee'
19
20class MeshbluRequest
21 constructor: (options={}) ->
22 {@protocol, @hostname, @port} = options
23 {@service, @domain, @secure, @resolveSrv} = options
24 {@dnsHttpServer} = options
25
26 delete: (pathname, options, callback) =>
27 requestOptions = _.pick(options, 'uuid', 'token', 'bearerToken', 'headers')
28 requestOptions.pathname = pathname
29 query = qs.stringify options.query
30
31 @_resolveBaseUrl (error, baseUri) =>
32 return callback error if error?
33 @_request('delete', baseUri, requestOptions).query(query).end @_handleResponse(callback)
34
35 get: (pathname, options, callback) =>
36 requestOptions = _.pick(options, 'uuid', 'token', 'bearerToken', 'headers')
37 requestOptions.pathname = pathname
38 query = qs.stringify options.query
39
40 @_resolveBaseUrl (error, baseUri) =>
41 return callback error if error?
42 @_request('get', baseUri, requestOptions).query(query).end @_handleResponse(callback)
43
44 patch: (pathname, options, callback) =>
45 requestOptions = _.pick(options, 'uuid', 'token', 'bearerToken', 'headers')
46 requestOptions.pathname = pathname
47 body = options.body
48
49 @_resolveBaseUrl (error, baseUri) =>
50 return callback error if error?
51 @_request('patch', baseUri, requestOptions).send(body).end @_handleResponse(callback)
52
53 post: (pathname, options, callback) =>
54 requestOptions = _.pick(options, 'uuid', 'token', 'bearerToken', 'headers')
55 requestOptions.pathname = pathname
56 body = options.body
57
58 @_resolveBaseUrl (error, baseUri) =>
59 return callback error if error?
60 @_request('post', baseUri, requestOptions).send(body).end @_handleResponse(callback)
61
62 put: (pathname, options, callback) =>
63 requestOptions = _.pick(options, 'uuid', 'token', 'bearerToken', 'headers')
64 requestOptions.pathname = pathname
65 body = options.body
66
67 @_resolveBaseUrl (error, baseUri) =>
68 return callback error if error?
69 @_request('put', baseUri, requestOptions).send(body).end @_handleResponse(callback)
70
71 _getDomain: =>
72 parts = _.split @hostname, '.'
73 domainParts = _.takeRight parts, 2
74 return _.join domainParts, '.'
75
76 _getSrvAddress: =>
77 return "_#{@service}._#{@_getSrvProtocol()}.#{@domain}"
78
79 _getSrvProtocol: =>
80 return 'https' if @secure
81 return 'http'
82
83 _getSubdomain: =>
84 parts = _.split @hostname, '.'
85 subdomainParts = _.dropRight parts, 2
86 return _.join subdomainParts, '.'
87
88 _handleResponse: (callback) => (error, response) =>
89 return callback error if error?
90 return callback null if response.notFound
91 return callback new Error 'Invalid Response Code' unless response.ok
92 return callback null, response.body
93
94 _request: (method, baseUri, {pathname, uuid, token, bearerToken, headers}) =>
95 theRequest = superagent[method](@_url baseUri, pathname)
96 theRequest.auth uuid, token if uuid? && token?
97 theRequest.set('Authorization', "Bearer #{bearerToken}") if bearerToken?
98 theRequest.accept('application/json')
99 theRequest.set('Content-Type', 'application/json')
100 _.each headers, (value, key) =>
101 theRequest.set key, value
102 return theRequest
103
104 _resolveBaseUrl: (cb) =>
105 callback = discardReturn cb
106
107 return callback null, url.format {@protocol, @hostname, @port} unless @resolveSrv
108
109 dns.resolveSrv @_getSrvAddress(), (error, addresses) =>
110 return callback error if error?
111 return callback new Error('SRV record found, but contained no valid addresses') if _.isEmpty addresses
112 return callback null, @_resolveUrlFromAddresses(addresses)
113
114 _resolveUrlFromAddresses: (addresses) =>
115 address = _.minBy addresses, 'priority'
116 return url.format {
117 protocol: @_getSrvProtocol()
118 hostname: address.name
119 port: address.port
120 }
121
122 _url: (baseUri, pathname) =>
123 {protocol, hostname, port} = url.parse baseUri
124 return url.format({ hostname, protocol, port, pathname })
125
126module.exports = MeshbluRequest