From 492167e1d09d8c3df2d403533d36ceaa18ea712a Mon Sep 17 00:00:00 2001 From: Nathan Woodburn Date: Tue, 17 Jun 2025 22:43:54 +1000 Subject: [PATCH] feat: Update path to not need /hns --- README.md | 5 +- public/app.js | 6 +-- public/demo.html | 1 + public/index.html | 2 +- server.js | 132 +++++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 133 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index d570959..af0f172 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ npm start ``` Then access Handshake+IPFS content via: -- `http://localhost:3000/hns/example/` (replace "example" with a Handshake domain) +- `http://localhost:3000/ipfs.act` (replace "ipfs.act" with a Handshake domain) - Direct web interface at `http://localhost:3000` ## Testing @@ -74,5 +74,4 @@ curl http://localhost:3000/api/status ### 2. Testing with Sample Handshake Domains You can test with known Handshake domains that have IPFS content: -- `http://localhost:3000/hns/welcome/` - The Handshake welcome page -- `http://localhost:3000/hns/blog.namebase/` - Namebase blog \ No newline at end of file +- `http://localhost:3000/ipfs.act` - Example \ No newline at end of file diff --git a/public/app.js b/public/app.js index d502ae4..2321c25 100644 --- a/public/app.js +++ b/public/app.js @@ -29,7 +29,7 @@ document.addEventListener('DOMContentLoaded', () => { }); }); - // Function to navigate to HNS domain + // Function to navigate to HNS domain (using new URL format) function navigateToHnsDomain() { const domain = domainInput.value.trim(); @@ -41,8 +41,8 @@ document.addEventListener('DOMContentLoaded', () => { // Clean up domain input (remove trailing slashes) const cleanDomain = domain.replace(/\/+$/, ''); - // Navigate to the HNS domain - window.location.href = `/hns/${cleanDomain}`; + // Navigate to the HNS domain using new format + window.location.href = `/${cleanDomain}`; } // Check server status diff --git a/public/demo.html b/public/demo.html index 4738802..d357e96 100644 --- a/public/demo.html +++ b/public/demo.html @@ -4,6 +4,7 @@ IPFS.act +

IPFS.act

diff --git a/public/index.html b/public/index.html index b1992b2..3ef5ba3 100644 --- a/public/index.html +++ b/public/index.html @@ -45,7 +45,7 @@

- URL format: https://ipfs.woodburn.au/hns/[domain]/[path]
+ URL format: https://ipfs.woodburn.au/[domain]/[path]
Replace [domain] with any Handshake domain and [path] with an optional path.

diff --git a/server.js b/server.js index a76f4ff..dd0888a 100644 --- a/server.js +++ b/server.js @@ -13,9 +13,134 @@ const app = express(); app.use(cors()); app.use(morgan('dev')); app.use(express.json()); + +// Define reserved paths that should not be treated as Handshake domains +const RESERVED_PATHS = [ + 'api', + 'hns', + 'public', + 'assets', + 'static', + 'images', + 'css', + 'js', + 'favicon.ico' +]; + +// Serve static files app.use(express.static(path.join(__dirname, 'public'))); -// Routes +// Status endpoint +app.get('/api/status', (req, res) => { + res.json({ status: 'online', version: '0.1.1' }); +}); + +// New route: Handle root domain requests with direct domain format +app.get('/:domain', async (req, res, next) => { + const domain = req.params.domain; + + // Skip this handler for reserved paths + if (RESERVED_PATHS.includes(domain)) { + return next(); + } + + try { + console.log(`Processing request for domain root: ${domain}`); + + // Resolve Handshake domain to get IPFS CID + const cid = await resolveHandshake(domain); + + if (!cid) { + console.warn(`No IPFS CID found for domain: ${domain}`); + return res.status(404).json({ + error: 'Domain not found or has no IPFS record', + domain: domain + }); + } + + console.log(`Resolved ${domain} to IPFS CID: ${cid}`); + + // Fetch content from IPFS (root path) + const content = await fetchFromIpfs(cid, ''); + + if (!content) { + return res.status(404).json({ + error: 'Content not found on IPFS network', + cid: cid + }); + } + + // Set appropriate content type + if (content.mimeType) { + res.setHeader('Content-Type', content.mimeType); + } + + // Return the content + res.send(content.data); + } catch (error) { + console.error('Error handling request:', error); + res.status(500).json({ + error: 'Server error processing request', + message: error.message + }); + } +}); + +// New route: Handle domain requests with subpaths using direct domain format +app.get('/:domain/*', async (req, res, next) => { + const domain = req.params.domain; + + // Skip this handler for reserved paths + if (RESERVED_PATHS.includes(domain)) { + return next(); + } + + try { + const subPath = req.params[0] || ''; + + console.log(`Processing request for domain: ${domain}, path: ${subPath}`); + + // Resolve Handshake domain to get IPFS CID + const cid = await resolveHandshake(domain); + + if (!cid) { + console.warn(`No IPFS CID found for domain: ${domain}`); + return res.status(404).json({ + error: 'Domain not found or has no IPFS record', + domain: domain + }); + } + + console.log(`Resolved ${domain} to IPFS CID: ${cid}`); + + // Fetch content from IPFS + const content = await fetchFromIpfs(cid, subPath); + + if (!content) { + return res.status(404).json({ + error: 'Content not found on IPFS network', + cid: cid, + path: subPath + }); + } + + // Set appropriate content type + if (content.mimeType) { + res.setHeader('Content-Type', content.mimeType); + } + + // Return the content + res.send(content.data); + } catch (error) { + console.error('Error handling request:', error); + res.status(500).json({ + error: 'Server error processing request', + message: error.message + }); + } +}); + +// Routes (keeping original routes for backward compatibility) app.get('/hns/:domain/*', async (req, res) => { try { const domain = req.params.domain; @@ -109,11 +234,6 @@ app.get('/hns/:domain', async (req, res) => { } }); -// Status endpoint -app.get('/api/status', (req, res) => { - res.json({ status: 'online', version: '0.1.0' }); -}); - // Start server app.listen(PORT, () => { console.log(`Fire Portal server running on port ${PORT}`);