Repository navigation
Expand file tree
/
Copy pathserver.js
More file actions
77 lines (63 loc) · 2.21 KB
/
Copy pathserver.js
File metadata and controls
77 lines (63 loc) · 2.21 KB
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
"use strict";
const express = require("express");
const { resolveNamespace } = require("./fabricConnect");
const { getCached, setCached, cacheStats } = require("./cache");
const PORT = process.env.PORT || 3000;
const DID_PREFIX = "did:rwp:";
// UUIDv4 per RWP-23 (canonical Global Namespace Identifier).
const NAMESPACE_RE =
/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
const app = express();
app.disable("x-powered-by");
/**
* Extracts a namespace from either a raw namespace or a full did:rwp DID.
* Returns null if the input is neither.
*/
function extractNamespace(id) {
if (typeof id !== "string" || id.length === 0) return null;
if (id.startsWith(DID_PREFIX)) {
const namespace = id.slice(DID_PREFIX.length).split(":")[0];
return NAMESPACE_RE.test(namespace) ? namespace : null;
}
return NAMESPACE_RE.test(id) ? id : null;
}
// No Fabric round-trip: cheap liveness probe for container/orchestrator health checks.
app.get("/health", (_req, res) => {
res.json({ status: "ok", cache: cacheStats() });
});
app.get("/resolve", async (req, res) => {
const rawId = req.query.id;
const namespace = extractNamespace(rawId);
if (!namespace) {
return res.status(400).json({
error: "Invalid id. Provide a namespace (UUIDv4) or a did:rwp:<namespace>:... identifier.",
});
}
const cached = getCached(namespace);
if (cached) {
return res.json({
namespace,
resolverEndpoint: cached.resolverEndpoint,
cacheAge: cached.ageSeconds,
});
}
try {
const result = await resolveNamespace(namespace);
if (!result || !result.resolverEndpoint) {
return res.status(404).json({ error: `Namespace not registered: ${namespace}` });
}
setCached(namespace, result.resolverEndpoint);
return res.json({
namespace,
resolverEndpoint: result.resolverEndpoint,
cacheAge: 0,
});
} catch (err) {
console.error("Resolution failed:", err.message);
return res.status(502).json({ error: "Root-resolver network unreachable or chaincode error." });
}
});
app.use((_req, res) => res.status(404).json({ error: "Not found." }));
app.listen(PORT, () => {
console.log(`rootresolver listening on http://localhost:${PORT}`);
});