Skip to content

Commit

Permalink
fix(server): 🩹 Using sessionID as a fallback to requests where refere…
Browse files Browse the repository at this point in the history
…r is missing.

Signed-off-by: Nishant Arora <[email protected]>
  • Loading branch information
whizzzkid committed Oct 20, 2023
1 parent 89c8854 commit 18aca9b
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 18 deletions.
77 changes: 77 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"homepage": "https://github.com/whizzzkid/helia-docker#readme",
"devDependencies": {
"@types/express": "4.x",
"@types/express-session": "1.17.9",
"@types/mime-types": "2.x",
"@types/node": "20.x",
"aegir": "40.x",
Expand All @@ -48,6 +49,7 @@
"@helia/unixfs": "1.x",
"express": "4.x",
"express-prom-bundle": "6.x",
"express-session": "1.17.3",
"file-type": "18.x",
"helia": "2.x",
"lru-cache": "10.x",
Expand Down
52 changes: 38 additions & 14 deletions src/heliaServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,23 +59,36 @@ export class HeliaServer {
]
}

/**
* Computes referer path for the request.
*/
private fetchRefererPath ({ request }: IRouteHandler): string {
let refererPath = new URL(request.headers.referer ?? 'http://ipfs.io').pathname
if (refererPath === '/') {
refererPath = request.sessionID
}

if (refererPath !== undefined) {
return refererPath
}

throw new Error('Error calculating referer')
}

/**
* Handles redirecting to the relative path
*/
private async redirectRelative ({ request, response }: IRouteHandler): Promise<void> {
try {
const referrerPath = new URL(request.headers.referer ?? '').pathname
if (referrerPath !== undefined) {
this.log('Referer found:', referrerPath)
let relativeRedirectPath = `${referrerPath}${request.path}`
const { namespace, address } = this.heliaFetch.parsePath(referrerPath)
if (namespace === 'ipns') {
relativeRedirectPath = `/${namespace}/${address}${request.path}`
}
// absolute redirect
this.log('Redirecting to relative to referer:', referrerPath)
response.redirect(relativeRedirectPath)
const refererPath = this.fetchRefererPath({ request, response })
let relativeRedirectPath = `${refererPath}${request.path}`
const { namespace, address } = this.heliaFetch.parsePath(refererPath)
if (namespace === 'ipns') {
relativeRedirectPath = `/${namespace}/${address}${request.path}`
}
// absolute redirect
this.log('Redirecting to relative to referer:', refererPath)
response.redirect(relativeRedirectPath)
} catch (error) {
this.log('Error redirecting to relative path:', error)
response.status(500).end()
Expand Down Expand Up @@ -113,9 +126,8 @@ export class HeliaServer {
address: reqDomain
} = this.heliaFetch.parsePath(request.path)

if (request.headers.referer !== undefined) {
this.log('Referer found:', request.headers.referer)
const refererPath = new URL(request.headers.referer).pathname
try {
const refererPath = this.fetchRefererPath({ request, response })
const {
namespace: refNamespace,
address: refDomain
Expand All @@ -131,6 +143,8 @@ export class HeliaServer {
return true
}
}
} catch (error) {
this.log('Error checking for additional redirection:', error)
}
return false
}
Expand Down Expand Up @@ -190,4 +204,14 @@ export class HeliaServer {
await this.heliaFetch.node?.gc()
response.status(200).end()
}

/**
* Generates a session ID for the request.
* This is a very ghetto way of identifying what the root ipns path for a request is.
* Overloading the sessionID the first request allows us to use the same session for all subsequent requests. Mostly!
* In many cases it won't work, but the browser won't care for those either.
*/
public sessionId (request: Request): string {
return request.sessionID ?? request.path
}
}
13 changes: 9 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
import debug from 'debug'
import express from 'express'
import promBundle from 'express-prom-bundle'
import session from 'express-session'
import { HeliaServer, type IRouteEntry } from './heliaServer.js'

const logger = debug('helia-server')
const app = express()
const promMetricsMiddleware = promBundle({ includeMethod: true })

const heliaServer = new HeliaServer(logger)
await heliaServer.isReady

// Constants
const PORT = (process?.env?.PORT ?? 8080) as number
const HOST = process?.env?.HOST ?? '0.0.0.0'

// Add the prometheus middleware
const app = express()
app.use(promMetricsMiddleware)

const heliaServer = new HeliaServer(logger)
await heliaServer.isReady
app.use(session({
genid: heliaServer.sessionId,
secret: 'very secret value'
}))

// Add the routes
app.get('/', (req, res) => {
Expand Down

0 comments on commit 18aca9b

Please sign in to comment.