forked from ipfs/public-gateway-checker
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGatewayNode.ts
156 lines (132 loc) · 5.33 KB
/
GatewayNode.ts
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import { URL } from 'url-ponyfill'
import { Cors } from './Cors'
import { Flag } from './Flag'
import { Origin } from './Origin'
import { Trustless } from './Trustless'
import type { Results } from './Results'
import { Status } from './Status'
import { UiComponent } from './UiComponent'
import { Log } from './Log'
import { gatewayHostname } from './gatewayHostname'
import { HASH_TO_TEST } from './constants'
import { IPNSCheck } from './Ipns'
const log = new Log('GatewayNode')
class GatewayNode extends UiComponent /* implements Checkable */ {
// tag: Tag
status: Status
cors: Cors
ipns: IPNSCheck
origin: Origin
trustless: Trustless
link: HTMLDivElement & { url?: URL }
flag: Flag
took: HTMLDivElement
gateway: string
index: unknown
checkingTime: number
atLeastOneSuccess = false
constructor (readonly parent: Results, gateway: string, index: unknown) {
super(parent, 'div', 'Node')
this.tag.empty()
this.tag.style.order = Date.now().toString()
this.status = new Status(this)
this.tag.append(this.status.tag)
this.cors = new Cors(this)
this.tag.append(this.cors.tag)
this.ipns = new IPNSCheck(this)
this.tag.append(this.ipns.tag)
this.origin = new Origin(this)
this.tag.append(this.origin.tag)
this.trustless = new Trustless(this)
this.tag.append(this.trustless.tag)
this.link = document.createElement('div')
const gatewayAndHash = gateway.replace(':hash', HASH_TO_TEST)
this.link.url = new URL(gatewayAndHash)
this.link.textContent = gatewayHostname(this.link.url)
this.link.className = 'Link'
this.flag = new Flag(this, this.link.textContent)
// this.link.prepend(this.flag.tag.element)
this.tag.append(this.flag.tag)
this.tag.append(this.link)
this.took = document.createElement('div')
this.took.className = 'Took'
this.tag.append(this.took)
this.gateway = gateway
this.index = index
this.checkingTime = 0
}
public async check (): Promise<void> {
this.checkingTime = Date.now()
// const onFailedCheck = () => { this.status.down = true }
// const onSuccessfulCheck = () => { this.status.up = true }
void this.flag.check().then(() => log.debug(this.gateway, 'Flag success'))
const onlineChecks = [
// this.flag.check().then(() => log.debug(this.gateway, 'Flag success')),
this.status.check().then(() => log.debug(this.gateway, 'Status success')).then(this.onSuccessfulCheck.bind(this)),
this.cors.check().then(() => log.debug(this.gateway, 'CORS success')).then(this.onSuccessfulCheck.bind(this)),
this.ipns.check().then(() => log.debug(this.gateway, 'IPNS success')).then(this.onSuccessfulCheck.bind(this)),
this.origin.check().then(() => log.debug(this.gateway, 'Origin success')).then(this.onSuccessfulCheck.bind(this)),
this.trustless.check().then(
() => log.debug(this.gateway, 'Trustless success')).then(this.onSuccessfulCheck.bind(this))
]
// we care only about the fastest method to return a success
// Promise.race(onlineChecks).catch((err) => {
// log.error('Promise race error', err)
// })
// await Promise.all(onlineChecks).catch(onFailedCheck)
await Promise.allSettled(onlineChecks).then((results) => results.map((result) => {
return result.status
})).then((statusArray) => {
if (statusArray.includes('fulfilled')) {
// At least promise was successful, which means the gateway is online
log.debug(`For gateway '${this.gateway}', at least one promise was successfully fulfilled`)
log.debug(this.gateway, 'this.status.up: ', this.status.up)
log.debug(this.gateway, 'this.status.down: ', this.status.down)
this.status.up = true
log.debug(this.gateway, 'this.status.up: ', this.status.up)
log.debug(this.gateway, 'this.status.down: ', this.status.down)
} else {
// No promise was successful, the gateway is down.
this.status.down = true
log.debug(`For gateway '${this.gateway}', all promises were rejected`)
}
})
}
private onSuccessfulCheck (): void {
if (!this.atLeastOneSuccess) {
log.info(`For gateway '${this.gateway}', at least one check was successful`)
this.atLeastOneSuccess = true
this.status.up = true
const url = this.link.url
if (url != null) {
const host = gatewayHostname(url)
// const anchor = document.createElement('a')
// anchor.title = host
// anchor.href = `${url.toString()}#x-ipfs-companion-no-redirect`
// anchor.target = '_blank'
// anchor.textContent = host
// this.flag.tag.element.remove()
// this.link.textContent = ''
// this.link.append(this.flag.tag.element, anchor)
this.link.innerHTML = `<a title="${host}" href="${url.toString()}#x-ipfs-companion-no-redirect" target="_blank">${host}</a>`
}
const ms = Date.now() - this.checkingTime
this.tag.style.order = ms.toString()
const s = (ms / 1000).toFixed(2)
this.took.textContent = `${s}s`
}
}
// private checked () {
// if (!this.doneChecking) {
// this.doneChecking = true
// // this.status.checked()
// // this.parent.checked()
// } else {
// log.warn('"checked" method called more than once.. potential logic error')
// }
// }
onerror (): void {
this.tag.err()
}
}
export { GatewayNode }