proxy WIP: fix async & TCP, addr redaction

pull/97/merge
lyc8503 2025-04-08 22:42:37 +08:00
parent 55900836d4
commit c248bddf1c
1 changed files with 34 additions and 34 deletions

View File

@ -1,6 +1,7 @@
// This is a Node.js implementation of status monitoring // This is a Node.js implementation of status monitoring
const location = '' const location = ''
const defaultTimeout = 5000 // 5 seconds, a lower default for deployments on platforms like Vercel
const express = require('express') const express = require('express')
const net = require('net') const net = require('net')
@ -22,15 +23,6 @@ const fetchTimeout = (url, ms, options = {}) => {
return promise.finally(() => clearTimeout(timeout)) return promise.finally(() => clearTimeout(timeout))
} }
function withTimeout(millis, promise) {
const timeout = new Promise((resolve, reject) =>
setTimeout(() => reject(new Error(`Promise timed out after ${millis}ms`)), millis)
)
return Promise.race([promise, timeout])
}
// TODO: More code reuse here // TODO: More code reuse here
async function getStatus(monitor) { async function getStatus(monitor) {
let status = { let status = {
@ -43,41 +35,49 @@ async function getStatus(monitor) {
if (monitor.method === 'TCP_PING') { if (monitor.method === 'TCP_PING') {
// TCP port endpoint monitor // TCP port endpoint monitor
let host, port
try { try {
// This is not a real https connection, but we need to add a dummy `https://` to parse the hostname & port // This is not a real https connection, but we need to add a dummy `https://` to parse the hostname & port
// TODO: ipv6 buggy
const parsed = new URL("https://" + monitor.target) const parsed = new URL("https://" + monitor.target)
host = parsed.hostname
port = parsed.port
await new Promise((resolve, reject) => {
const socket = net.createConnection({ host: host, port: Number(port) })
const client = await net.createConnection( const timer = setTimeout(() => {
{ host: parsed.hostname, port: Number(parsed.port) }, socket.destroy()
() => { reject(new Error(`Timeout after ${monitor.timeout || defaultTimeout}ms`))
console.log(`${monitor.name} connected to ${monitor.target}`) }, monitor.timeout || defaultTimeout)
status.ping = Date.now() - startTime
status.up = true socket.on('connect', () => {
status.err = '' clearTimeout(timer)
client.end() socket.end()
resolve(null)
})
socket.on('error', (err) => {
clearTimeout(timer)
socket.destroy()
reject(err)
})
} }
) )
// const socket = connect({ hostname: parsed.hostname, port: Number(parsed.port) }) status.up = true
status.err = ''
// // Now we have an `opened` promise! status.ping = Date.now() - startTime
// // @ts-ignore
// await withTimeout(monitor.timeout || 10000, socket.opened)
// await socket.close()
} catch (e) { } catch (e) {
console.log(`${monitor.name} errored with ${e.name}: ${e.message}`) console.log(`${monitor.name} errored with ${e.name}: ${e.message}`)
if (e.message.includes('timed out')) {
status.ping = monitor.timeout || 10000
}
status.up = false status.up = false
status.err = e.name + ': ' + e.message status.err = e.name + ': ' + e.message.replace(host, '<redacted>').replace(port, '<redacted>')
status.ping = Date.now() - startTime
} }
} else { } else {
// HTTP endpoint monitor // HTTP endpoint monitor
try { try {
const response = await fetchTimeout(monitor.target, monitor.timeout || 10000, { const response = await fetchTimeout(monitor.target, monitor.timeout || defaultTimeout, {
method: monitor.method, method: monitor.method,
headers: monitor.headers, headers: monitor.headers,
body: monitor.body, body: monitor.body,
@ -129,7 +129,7 @@ async function getStatus(monitor) {
} catch (e) { } catch (e) {
console.log(`${monitor.name} errored with ${e.name}: ${e.message}`) console.log(`${monitor.name} errored with ${e.name}: ${e.message}`)
if (e.name === 'AbortError') { if (e.name === 'AbortError') {
status.ping = monitor.timeout || 10000 status.ping = monitor.timeout || defaultTimeout
status.up = false status.up = false
status.err = `Timeout after ${status.ping}ms` status.err = `Timeout after ${status.ping}ms`
} else { } else {
@ -144,11 +144,11 @@ async function getStatus(monitor) {
app.use(express.json()); app.use(express.json());
app.post('/', (req, res) => { app.post('/', async (req, res) => {
res.json( res.json(
{ {
location: getWorkerLocation(), location: await getWorkerLocation(),
status: getStatus(req.body), status: await getStatus(req.body),
} }
) )
}) })