Files
peardata/server/rest/http-server.js
T
Raven Scott 3fc0245b32
CI / test (push) Successful in 1m3s
Release rolling / release (push) Has been cancelled
Updates
2026-07-18 23:47:54 -04:00

90 lines
2.7 KiB
JavaScript

/**
* Optional agent-style HTTP API bound to the PearMonitor agent.
*
* Default: 127.0.0.1:18888 — local only.
* Disable with PEARDATA_REST=0
*/
import http from 'http'
import b4a from 'b4a'
import { handleRest } from './routes.js'
import logger from '../utils/logger.js'
const log = logger.child('rest')
/**
* @returns {http.Server|null}
*/
export function startRestServer() {
if (process.env.PEARDATA_REST === '0' || process.env.PEARDATA_REST === 'off') {
log.info('REST API disabled (PEARDATA_REST=0)')
return null
}
const host = process.env.PEARDATA_REST_HOST || '127.0.0.1'
const port = Number(process.env.PEARDATA_REST_PORT) || 18888
const server = http.createServer(async (req, res) => {
try {
const url = new URL(req.url || '/', `http://${host}:${port}`)
if (req.method !== 'GET' && req.method !== 'HEAD' && req.method !== 'OPTIONS') {
res.writeHead(405, { 'content-type': 'application/json', allow: 'GET, HEAD, OPTIONS' })
res.end(JSON.stringify({ error: 'method not allowed' }))
return
}
if (req.method === 'OPTIONS') {
res.writeHead(204, corsHeaders())
res.end()
return
}
const result = await handleRest(url.pathname, url.searchParams)
const headers = {
...corsHeaders(),
'content-type': result.contentType || 'application/json',
'cache-control': 'no-cache',
'x-peardata-api': 'v3',
}
const body =
typeof result.body === 'string' ? result.body : JSON.stringify(result.body, null, 0)
if (req.method === 'HEAD') {
headers['content-length'] = b4a.byteLength(body)
res.writeHead(result.status || 200, headers)
res.end()
return
}
res.writeHead(result.status || 200, headers)
res.end(body)
} catch (err) {
log.error('REST handler error', { error: err.message })
res.writeHead(500, { 'content-type': 'application/json' })
res.end(JSON.stringify({ error: 'internal error' }))
}
})
server.listen(port, host, () => {
log.info('REST API listening', {
url: `http://${host}:${port}`,
examples: [
`http://${host}:${port}/api/v3/info`,
`http://${host}:${port}/api/v3/data?chart=system.cpu&after=-60&points=60`,
`http://${host}:${port}/api/v1/charts`,
],
})
})
server.on('error', (err) => {
log.error('REST server error', { error: err.message })
})
return server
}
function corsHeaders() {
return {
'access-control-allow-origin': process.env.PEARDATA_REST_CORS || '*',
'access-control-allow-methods': 'GET, HEAD, OPTIONS',
'access-control-allow-headers': 'Content-Type, Authorization',
}
}