Skip to content

Commit

Permalink
Lock down failure cases in ipfs gateway routes (#245)
Browse files Browse the repository at this point in the history
  • Loading branch information
SidSethi committed Jan 17, 2020
1 parent b87cade commit 444964d
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 20 deletions.
37 changes: 25 additions & 12 deletions creator-node/src/routes/files.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,12 @@ module.exports = function (app) {
// Do not act as a public gateway. Only serve IPFS files that are hosted by this creator node.
const CID = req.params.CID

// Don't serve if blacklisted
// Don't serve if blacklisted.
if (await req.app.get('blacklistManager').CIDIsInBlacklist(CID)) {
return sendResponse(req, res, errorResponseForbidden(`CID ${CID} has been blacklisted by this node.`))
}

// Don't serve if not found in DB
// Don't serve if not found in DB.
const queryResults = await models.File.findOne({ where: {
multihash: CID,
// All other file types are valid and can be served through this route.
Expand All @@ -173,12 +173,19 @@ module.exports = function (app) {
logger.info(`IPFS Standalone Request - ${CID}`)
logger.info(`IPFS Stats - Standalone Requests: ${totalStandaloneIpfsReqs}`)

// Conditionally re-add from filestorage to IPFS
await rehydrateIpfsFromFsIfNecessary(
req,
CID,
queryResults.storagePath)
// Conditionally rehydrate from filestorage to IPFS.
try {
await rehydrateIpfsFromFsIfNecessary(
req,
CID,
queryResults.storagePath
)
} catch (e) {
// If rehydrate throws error, return 500 without attempting to stream file.
return sendResponse(req, res, errorResponseServerError(e.message))
}

// Stream file to client.
try {
// If client has provided filename, set filename in header to be auto-populated in download prompt.
if (req.query.filename) {
Expand Down Expand Up @@ -217,11 +224,17 @@ module.exports = function (app) {
}

// Conditionally re-add from filestorage to IPFS
await rehydrateIpfsFromFsIfNecessary(
req,
dirCID,
queryResults.storagePath,
filename)
try {
await rehydrateIpfsFromFsIfNecessary(
req,
dirCID,
queryResults.storagePath,
filename
)
} catch (e) {
// If rehydrate throws error, return 500 without attempting to stream file.
return sendResponse(req, res, errorResponseServerError(e.message))
}

// TODO - check if file with filename is also stored in CNODE

Expand Down
26 changes: 18 additions & 8 deletions creator-node/src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,18 @@ async function getIPFSPeerId (ipfs, config) {

const wait = (ms) => new Promise((resolve, reject) => setTimeout(() => reject(new Error('Timeout')), ms))

/** Cat single byte of file at given filepath. */
const ipfsSingleByteCat = (path, req) => new Promise(async (resolve, reject) => {
// Cat single byte
const start = Date.now()
let ipfs = req.app.get('ipfsAPI')
await ipfs.cat(path, { length: 1 })
req.logger.info(`ipfsSingleByteCat - Retrieved ${path} in ${Date.now() - start}ms`)
resolve('SUCCESS')
try {
await ipfs.cat(path, { length: 1 })
req.logger.info(`ipfsSingleByteCat - Retrieved ${path} in ${Date.now() - start}ms`)
resolve()
} catch (e) {
req.logger.error(`ipfsSingleByteCat - Error: ${e}`)
reject(e)
}
})

const parseSourcePath = (sourcePath) => {
Expand All @@ -102,8 +107,13 @@ async function rehydrateIpfsFromFsIfNecessary (req, multihash, storagePath, file
try {
await Promise.race([
wait(1000),
ipfsSingleByteCat(ipfsPath, req)])
ipfsSingleByteCat(ipfsPath, req)]
)
} catch (e) {
// Do not attempt to rehydrate as file, if cat() indicates CID is of a dir.
if (e.message.includes('this dag node is a directory')) {
throw new Error(e.message)
}
rehydrateNecessary = true
req.logger.info(`rehydrateIpfsFromFsIfNecessary - error condition met ${ipfsPath}, ${e}`)
}
Expand All @@ -119,7 +129,7 @@ async function rehydrateIpfsFromFsIfNecessary (req, multihash, storagePath, file
req.logger.info(`rehydrateIpfsFromFsIfNecessary - Failed to find on disk, file - ${multihash}, stg path: ${storagePath}`)
}
} catch (e) {
req.logger.info(`rehydrateIpfsFromFsIfNecessary - ${e},Re-adding file - ${multihash}, stg path: ${storagePath}`)
req.logger.error(`rehydrateIpfsFromFsIfNecessary - failed to addFromFs ${e}, Re-adding file - ${multihash}, stg path: ${storagePath}`)
}
} else {
req.logger.info(`rehydrateIpfsFromFsIfNecessary - Re-adding dir ${multihash}, stg path: ${storagePath}, filename: ${filename}, ipfsPath: ${ipfsPath}`)
Expand Down Expand Up @@ -148,9 +158,9 @@ async function rehydrateIpfsFromFsIfNecessary (req, multihash, storagePath, file

try {
let addResp = await ipfs.add(ipfsAddArray, { pin: false })
req.logger.info(`rehydrateIpfsFromFsIfNecessary - ${JSON.stringify(addResp)}`)
req.logger.info(`rehydrateIpfsFromFsIfNecessary - addResp ${JSON.stringify(addResp)}`)
} catch (e) {
req.logger.info(`rehydrateIpfsFromFsIfNecessary - ERROR ${e}, ${ipfsAddArray}`)
req.logger.error(`rehydrateIpfsFromFsIfNecessary - addResp ${e}, ${ipfsAddArray}`)
}
}
}
Expand Down

0 comments on commit 444964d

Please sign in to comment.