|
2 | 2 |
|
3 | 3 | const mh = require('multihashes')
|
4 | 4 | const promisify = require('promisify-es6')
|
5 |
| -const reduce = require('async/reduce') |
6 | 5 | const CID = require('cids')
|
7 |
| -const Unixfs = require('ipfs-unixfs') |
8 | 6 | const debug = require('debug')
|
9 |
| -const log = debug('ipfs:http:response:resolver') |
10 |
| - |
| 7 | +const tryEach = require('async/tryEach') |
| 8 | +const waterfall = require('async/waterfall') |
| 9 | +const log = debug('jsipfs:http:response:resolver') |
| 10 | +log.error = debug('jsipfs:http:response:resolver:error') |
11 | 11 | const dirView = require('./dir-view')
|
12 |
| -const pathUtil = require('./utils/path') |
13 | 12 |
|
14 |
| -function getIndexFiles (links) { |
15 |
| - const INDEX_HTML_FILES = [ |
16 |
| - 'index.html', |
17 |
| - 'index.htm', |
18 |
| - 'index.shtml' |
19 |
| - ] |
20 |
| - // directory |
21 |
| - let indexes = links.filter((link) => INDEX_HTML_FILES.indexOf(link.Name) !== -1) |
22 |
| - if (indexes.length) { |
23 |
| - return indexes |
24 |
| - } |
25 |
| - // hamt-sharded-directory uses a 2 char prefix |
26 |
| - return links.filter((link) => { |
27 |
| - return link.Name.length > 2 && INDEX_HTML_FILES.indexOf(link.Name.substring(2)) !== -1 |
28 |
| - }) |
| 13 | +const INDEX_HTML_FILES = [ |
| 14 | + 'index.html', |
| 15 | + 'index.htm', |
| 16 | + 'index.shtml' |
| 17 | +] |
| 18 | + |
| 19 | +const findIndexFile = (ipfs, path, callback) => { |
| 20 | + return tryEach(INDEX_HTML_FILES.map(file => { |
| 21 | + return (cb) => { |
| 22 | + waterfall([ |
| 23 | + (cb) => ipfs.files.stat(`${path}/${file}`, cb), |
| 24 | + (stats, cb) => cb(null, { |
| 25 | + name: file, |
| 26 | + cid: new CID(stats.hash) |
| 27 | + }) |
| 28 | + ], cb) |
| 29 | + } |
| 30 | + }), callback) |
29 | 31 | }
|
30 | 32 |
|
31 | 33 | const directory = promisify((ipfs, path, cid, callback) => {
|
32 |
| - cid = new CID(cid) |
33 |
| - |
34 |
| - ipfs.object.get(cid.buffer, (err, dagNode) => { |
| 34 | + // Test if it is a Website |
| 35 | + findIndexFile(ipfs, path, (err, res) => { |
35 | 36 | if (err) {
|
36 |
| - return callback(err) |
37 |
| - } |
| 37 | + if (err.message.includes('does not exist')) { |
| 38 | + // not a website, just show a directory listing |
| 39 | + return ipfs.dag.get(cid, (err, result) => { |
| 40 | + if (err) { |
| 41 | + return callback(err) |
| 42 | + } |
38 | 43 |
|
39 |
| - // Test if it is a Website |
40 |
| - const indexFiles = getIndexFiles(dagNode.Links) |
| 44 | + return callback(null, dirView.render(path, result.value.Links)) |
| 45 | + }) |
| 46 | + } |
41 | 47 |
|
42 |
| - if (indexFiles.length) { |
43 |
| - return callback(null, indexFiles) |
| 48 | + return callback(err) |
44 | 49 | }
|
45 | 50 |
|
46 |
| - return callback(null, dirView.render(path, dagNode.Links)) |
| 51 | + callback(err, [{ |
| 52 | + Name: res.name |
| 53 | + }]) |
47 | 54 | })
|
48 | 55 | })
|
49 | 56 |
|
50 | 57 | const cid = promisify((ipfs, path, callback) => {
|
51 |
| - const parts = pathUtil.cidArray(path) |
52 |
| - let firstCid = parts.shift() |
53 |
| - let currentCid |
54 |
| - |
55 |
| - // TODO: replace below with ipfs.resolve(path, {recursive: true}) |
56 |
| - // (requires changes to js-ipfs/js-ipfs-api) |
57 |
| - |
58 |
| - reduce( |
59 |
| - parts, |
60 |
| - firstCid, |
61 |
| - (memo, item, next) => { |
62 |
| - try { |
63 |
| - currentCid = new CID(memo) |
64 |
| - } catch (err) { |
65 |
| - return next(err) |
66 |
| - } |
67 |
| - |
68 |
| - log('memo: ', memo) |
69 |
| - log('item: ', item) |
70 |
| - |
71 |
| - ipfs.dag.get(currentCid, (err, result) => { |
72 |
| - if (err) { |
73 |
| - return next(err) |
74 |
| - } |
75 |
| - |
76 |
| - const dagNode = result.value |
77 |
| - // find multihash/cid of requested named-file in current dagNode's links |
78 |
| - let cidOfNextFile |
79 |
| - const nextFileName = item |
80 |
| - |
81 |
| - try { |
82 |
| - for (let link of dagNode.Links) { |
83 |
| - if (link.Name === nextFileName) { |
84 |
| - cidOfNextFile = link.Hash |
85 |
| - break |
86 |
| - } |
87 |
| - } |
88 |
| - } catch (err) { |
89 |
| - return next(err) |
90 |
| - } |
91 |
| - |
92 |
| - if (!cidOfNextFile) { |
93 |
| - const missingLinkErr = new Error(`no link named "${nextFileName}" under ${memo}`) |
94 |
| - missingLinkErr.parentDagNode = memo |
95 |
| - missingLinkErr.missingLinkName = nextFileName |
96 |
| - return next(missingLinkErr) |
97 |
| - } |
98 |
| - |
99 |
| - next(null, cidOfNextFile) |
100 |
| - }) |
101 |
| - }, (err, cid) => { |
102 |
| - if (err) { |
103 |
| - return callback(err) |
104 |
| - } |
105 |
| - |
106 |
| - try { |
107 |
| - cid = new CID(cid) |
108 |
| - } catch (err) { |
109 |
| - return callback(err) |
110 |
| - } |
| 58 | + ipfs.files.stat(path, (err, stats) => { |
| 59 | + if (err) { |
| 60 | + return callback(err) |
| 61 | + } |
111 | 62 |
|
112 |
| - if (cid.codec === 'raw') { |
113 |
| - // no need for additional lookup, its raw data |
114 |
| - callback(null, { cid }) |
115 |
| - } |
| 63 | + const cid = new CID(stats.hash) |
116 | 64 |
|
117 |
| - ipfs.dag.get(cid, (err, dagResult) => { |
118 |
| - if (err) { |
119 |
| - return callback(err) |
120 |
| - } |
| 65 | + if (stats.type.includes('directory')) { |
| 66 | + const err = new Error('This dag node is a directory') |
| 67 | + err.cid = cid |
| 68 | + err.fileName = stats.name |
| 69 | + err.dagDirType = stats.type |
121 | 70 |
|
122 |
| - try { |
123 |
| - let dagDataObj = Unixfs.unmarshal(dagResult.value.Data) |
124 |
| - // There are at least two types of directories: |
125 |
| - // - "directory" |
126 |
| - // - "hamt-sharded-directory" (example: QmT5NvUtoM5nWFfrQdVrFtvGfKFmG7AHE8P34isapyhCxX) |
127 |
| - if (dagDataObj.type === 'directory' || dagDataObj.type === 'hamt-sharded-directory') { |
128 |
| - let isDirErr = new Error('This dag node is a directory') |
129 |
| - // store memo of last multihash so it can be used by directory |
130 |
| - isDirErr.cid = isDirErr.fileName = cid |
131 |
| - isDirErr.dagDirType = dagDataObj.type |
132 |
| - return callback(isDirErr) |
133 |
| - } |
134 |
| - } catch (err) { |
135 |
| - return callback(err) |
136 |
| - } |
| 71 | + return callback(err) |
| 72 | + } |
137 | 73 |
|
138 |
| - callback(null, { cid }) |
139 |
| - }) |
| 74 | + callback(err, { |
| 75 | + cid |
140 | 76 | })
|
| 77 | + }) |
141 | 78 | })
|
142 | 79 |
|
143 | 80 | const multihash = promisify((ipfs, path, callback) => {
|
|
0 commit comments