This repository was archived by the owner on Mar 10, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 297
/
Copy pathrequest-api.js
129 lines (101 loc) · 3.26 KB
/
request-api.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
'use strict'
const Wreck = require('wreck')
const Qs = require('qs')
const ndjson = require('ndjson')
const getFilesStream = require('./get-files-stream')
const isNode = require('detect-node')
// -- Internal
function parseChunkedJson (res, cb) {
const parsed = []
res
.pipe(ndjson.parse())
.on('data', parsed.push.bind(parsed))
.on('end', () => cb(null, parsed))
}
function onRes (buffer, cb) {
return (err, res) => {
if (err) {
return cb(err)
}
const stream = !!res.headers['x-stream-output']
const chunkedObjects = !!res.headers['x-chunked-output']
const isJson = res.headers['content-type'].indexOf('application/json') === 0
if (res.statusCode >= 400 || !res.statusCode) {
const error = new Error(`Server responded with ${res.statusCode}`)
return Wreck.read(res, {json: true}, (err, payload) => {
if (err) {
return cb(err)
}
if (payload) {
error.code = payload.Code
error.message = payload.Message || payload.toString()
}
cb(error)
})
}
if (stream && !buffer) return cb(null, res)
if (chunkedObjects) {
if (isJson) return parseChunkedJson(res, cb)
return Wreck.read(res, null, cb)
}
Wreck.read(res, {json: isJson}, cb)
}
}
function requestAPI (config, path, args, qs, files, buffer, cb) {
qs = qs || {}
if (Array.isArray(path)) path = path.join('/')
if (args && !Array.isArray(args)) args = [args]
if (args) qs.arg = args
if (files && !Array.isArray(files)) files = [files]
if (qs.r) {
qs.recursive = qs.r
delete qs.r // From IPFS 0.4.0, it throw an error when both r and recursive are passed
}
if (!isNode && qs.recursive && path === 'add') {
return cb(new Error('Recursive uploads are not supported in the browser'))
}
qs['stream-channels'] = true
let stream
if (files) {
stream = getFilesStream(files, qs)
}
// this option is only used internally, not passed to daemon
delete qs.followSymlinks
const port = config.port ? `:${config.port}` : ''
const opts = {
method: files ? 'POST' : 'GET',
uri: `${config.protocol}://${config.host}${port}${config['api-path']}${path}?${Qs.stringify(qs, {arrayFormat: 'repeat'})}`,
headers: {}
}
if (isNode) {
// Browsers do not allow you to modify the user agent
opts.headers['User-Agent'] = config['user-agent']
}
if (files) {
if (!stream.boundary) {
return cb(new Error('No boundary in multipart stream'))
}
opts.headers['Content-Type'] = `multipart/form-data; boundary=${stream.boundary}`
opts.downstreamRes = stream
opts.payload = stream
}
return Wreck.request(opts.method, opts.uri, opts, onRes(buffer, cb))
}
// -- Interface
exports = module.exports = function getRequestAPI (config) {
return function (path, args, qs, files, buffer, cb) {
if (typeof buffer === 'function') {
cb = buffer
buffer = false
}
if (typeof cb !== 'function' && typeof Promise !== 'undefined') {
return new Promise(function (resolve, reject) {
requestAPI(config, path, args, qs, files, buffer, function (err, res) {
if (err) return reject(err)
resolve(res)
})
})
}
return requestAPI(config, path, args, qs, files, buffer, cb)
}
}