-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
103 lines (83 loc) · 2.43 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
const http = require('bare-http1')
const https = require('bare-https')
const { ReadableStream } = require('bare-stream/web')
const Request = require('./lib/request')
const Response = require('./lib/response')
const Headers = require('./lib/headers')
const errors = require('./lib/errors')
// https://fetch.spec.whatwg.org/#dom-global-fetch
module.exports = exports = function fetch(input, init = {}) {
let resolve
let reject
const promise = new Promise((res, rej) => {
resolve = res
reject = rej
})
const response = new Response()
process(input)
return promise
async function process(input) {
let request
try {
request = new Request(input, init)
} catch (err) {
return reject(err)
}
if (response._urls.length > 20) {
return reject(errors.TOO_MANY_REDIRECTS('Redirect count exceeded'))
}
let protocol
if (request._url.protocol === 'http:') {
protocol = http
} else if (request._url.protocol === 'https:') {
protocol = https
} else {
return reject(errors.UNKNOWN_PROTOCOL('Unknown protocol'))
}
response._urls.push(request._url)
if (!request._headers.has('user-agent')) {
request._headers.set('user-agent', `Bare/${Bare.version.substring(1)}`)
}
const req = protocol.request(
request._url,
{
method: request._method,
headers: Object.fromEntries(request._headers)
},
(res) => {
if (res.headers.location && isRedirectStatus(res.statusCode)) {
return process(res.headers.location)
}
response._body = new ReadableStream(res)
response._status = res.statusCode
response._statusText = res.statusMessage
for (const [name, value] of Object.entries(res.headers)) {
response._headers.set(name, value)
}
resolve(response)
}
)
req.on('error', (err) => reject(errors.NETWORK_ERROR('Network error', err)))
try {
if (request._body) {
for await (const data of request._body) req.write(data)
}
req.end()
} catch (err) {
return reject(errors.NETWORK_ERROR('Network error', err))
}
}
}
exports.Request = Request
exports.Response = Response
exports.Headers = Headers
// https://fetch.spec.whatwg.org/#redirect-status
function isRedirectStatus(status) {
return (
status === 301 ||
status === 302 ||
status === 303 ||
status === 307 ||
status === 308
)
}