-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
109 lines (90 loc) · 3.03 KB
/
index.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
var MediaType = require("medium-type")
var JSONS = ["application/json", "*/*+json"].map(MediaType.parse)
var XMLS = ["application/xml", "text/xml", "*/*+xml"].map(MediaType.parse)
var WILDCARD_PARSER = [[new MediaType("*/*"), null]]
var PARSER_TYPE_ERR = "Parser not a function or true for default: "
exports = module.exports = function(fetch, types) {
types = types == null ? WILDCARD_PARSER : parseParsers(types)
return assign(exports.fetch.bind(null, fetch, types), fetch)
}
exports.fetch = function(fetch, types, url, opts) {
return fetch(url, opts).then(exports.parse.bind(null, types))
}
exports.parse = function(types, res) {
if (!hasContent(res)) return res
var type = parseType(res.headers.get("content-type"))
if (type == null) return res
var parse = findParser(types, type)
return parse ? parse(res).then(exports.set.bind(null, res)) : res
}
exports.arrayBuffer = function(res) {
return res.arrayBuffer()
}
exports.text = function(res) {
return res.text()
}
exports.json = function(res) {
/* eslint consistent-return: 0 */
return res.text().then(function(body) {
if (body !== "") try { return JSON.parse(body) }
catch (ex) { exports.set(res, body); throw errorify(res, ex) }
else return undefined
})
}
exports.set = function(res, body) {
return Object.defineProperty(res, "body", {
value: body, configurable: true, writable: true, enumerable: true
})
}
function parseParsers(types) {
return reduce(function(pairs, parser, type) {
var types = expandType(type)
if (parser === true)
return pairs.concat(types.map(function(type) { return [type, null] }))
else if (typeof parser == "function")
return pairs.concat(types.map(function(type) { return [type, parser] }))
else
throw new TypeError(PARSER_TYPE_ERR + parser)
}, [], types)
}
function expandType(type) {
switch (type) {
case "json": return JSONS
case "xml": return XMLS
default: return [new MediaType(type)]
}
}
function hasContent(res) {
if (res.bodyUsed) return false
if (res.status === 204 || res.status === 304) return false
var contentType = res.headers.get("content-type")
return contentType != null && contentType !== ""
}
function parseType(type) {
try { return new MediaType(type) }
catch (ex) {
if (ex instanceof SyntaxError || ex instanceof TypeError) return null
else throw ex
}
}
function findParser(types, type) {
for (var i = 0; i < types.length; ++i)
if (type.match(types[i][0])) return types[i][1] || getDefaultParser(type)
return null
}
function getDefaultParser(type) {
if (type.type === "text") return exports.text
if (JSONS.some(type.match, type)) return exports.json
if (XMLS.some(type.match, type)) return exports.text
return exports.arrayBuffer
}
function errorify(res, err) {
return Object.defineProperty(err, "response", {
value: res, configurable: true, writable: true
})
}
function reduce(fn, left, obj) {
for (var key in obj) left = fn(left, obj[key], key)
return left
}
function assign(a, b) { for (var k in b) a[k] = b[k]; return a }