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