diff --git a/examples/explore-ethereum-blockchain/package.json b/examples/explore-ethereum-blockchain/package.json index 562ceba4fc..f199c02d4e 100644 --- a/examples/explore-ethereum-blockchain/package.json +++ b/examples/explore-ethereum-blockchain/package.json @@ -12,7 +12,7 @@ "devDependencies": { "ipfs": "^0.49.0", "ipfs-http-client": "^46.0.0", - "ipfsd-ctl": "^5.0.0", + "ipfsd-ctl": "^7.0.0", "test-ipfs-example": "^2.0.3" } } diff --git a/examples/http-client-browser-pubsub/package.json b/examples/http-client-browser-pubsub/package.json index 2eb24f82fb..c7e31e96d3 100644 --- a/examples/http-client-browser-pubsub/package.json +++ b/examples/http-client-browser-pubsub/package.json @@ -21,7 +21,7 @@ "execa": "^4.0.0", "go-ipfs": "^0.6.0", "ipfs": "^0.49.0", - "ipfsd-ctl": "^5.0.0", + "ipfsd-ctl": "^7.0.0", "parcel-bundler": "^1.12.4", "test-ipfs-example": "^2.0.3" } diff --git a/examples/http-client-bundle-webpack/package.json b/examples/http-client-bundle-webpack/package.json index a08781d979..8ad0b68cdf 100644 --- a/examples/http-client-bundle-webpack/package.json +++ b/examples/http-client-bundle-webpack/package.json @@ -24,7 +24,7 @@ "copy-webpack-plugin": "^5.0.4", "execa": "^4.0.0", "ipfs": "^0.49.0", - "ipfsd-ctl": "^5.0.0", + "ipfsd-ctl": "^7.0.0", "react-hot-loader": "^4.12.21", "test-ipfs-example": "^2.0.3", "webpack": "^4.43.0", diff --git a/examples/http-client-name-api/package.json b/examples/http-client-name-api/package.json index 17e5f548c4..76200a5491 100644 --- a/examples/http-client-name-api/package.json +++ b/examples/http-client-name-api/package.json @@ -17,7 +17,7 @@ "devDependencies": { "execa": "^4.0.0", "go-ipfs": "^0.6.0", - "ipfsd-ctl": "^5.0.0", + "ipfsd-ctl": "^7.0.0", "parcel-bundler": "^1.12.4", "test-ipfs-example": "^2.0.3" }, diff --git a/packages/interface-ipfs-core/package.json b/packages/interface-ipfs-core/package.json index 808d63943d..93dde85de4 100644 --- a/packages/interface-ipfs-core/package.json +++ b/packages/interface-ipfs-core/package.json @@ -63,7 +63,7 @@ }, "devDependencies": { "aegir": "^26.0.0", - "ipfsd-ctl": "^6.0.0" + "ipfsd-ctl": "^7.0.0" }, "contributors": [ "Alan Shaw ", diff --git a/packages/ipfs-http-client/package.json b/packages/ipfs-http-client/package.json index 9ef7a9d920..253edefe7f 100644 --- a/packages/ipfs-http-client/package.json +++ b/packages/ipfs-http-client/package.json @@ -58,7 +58,7 @@ "it-tar": "^1.2.2", "it-to-buffer": "^1.0.0", "it-to-stream": "^0.1.1", - "merge-options": "^2.0.0", + "merge-options": "^3.0.1", "multiaddr": "^8.0.0", "multiaddr-to-uri": "^6.0.0", "multibase": "^3.0.0", @@ -75,7 +75,7 @@ "cross-env": "^7.0.0", "go-ipfs": "^0.6.0", "interface-ipfs-core": "^0.139.1", - "ipfsd-ctl": "^6.0.0", + "ipfsd-ctl": "^7.0.0", "it-all": "^1.0.1", "it-concat": "^1.0.0", "it-pipe": "^1.1.0", diff --git a/packages/ipfs/package.json b/packages/ipfs/package.json index 9cd62d09d8..925006c2d1 100644 --- a/packages/ipfs/package.json +++ b/packages/ipfs/package.json @@ -62,11 +62,10 @@ "dep-check": "aegir dep-check" }, "dependencies": { - "@hapi/ammo": "^3.1.2", - "@hapi/boom": "^7.4.3", - "@hapi/content": "^4.1.0", - "@hapi/hapi": "^18.4.0", - "@hapi/joi": "^15.1.0", + "@hapi/ammo": "^5.0.1", + "@hapi/boom": "^9.1.0", + "@hapi/content": "^5.0.2", + "@hapi/hapi": "^20.0.0", "abort-controller": "^3.0.0", "any-signal": "^1.1.0", "array-shuffle": "^1.0.1", @@ -88,7 +87,7 @@ "fnv1a": "^1.0.1", "get-folder-size": "^2.0.0", "hamt-sharding": "^1.0.0", - "hapi-pino": "^6.1.0", + "hapi-pino": "^8.2.0", "hashlru": "^2.3.0", "interface-datastore": "^2.0.0", "ipfs-bitswap": "^3.0.0", @@ -126,6 +125,7 @@ "it-tar": "^1.2.2", "it-to-stream": "^0.1.1", "iterable-ndjson": "^1.1.0", + "joi": "^17.2.1", "jsondiffpatch": "^0.4.1", "just-safe-set": "^2.1.0", "libp2p": "libp2p/js-libp2p#0.29.x", @@ -142,10 +142,10 @@ "libp2p-record": "^0.9.0", "libp2p-secio": "^0.13.0", "libp2p-tcp": "^0.15.0", - "libp2p-webrtc-star": "^0.19.0", + "libp2p-webrtc-star": "^0.20.0", "libp2p-websockets": "^0.14.0", "mafmt": "^8.0.0", - "merge-options": "^2.0.0", + "merge-options": "^3.0.1", "mortice": "^2.0.0", "multiaddr": "^8.0.0", "multiaddr-to-uri": "^6.0.0", @@ -180,7 +180,7 @@ "go-ipfs": "^0.6.0", "interface-ipfs-core": "^0.139.1", "ipfs-interop": "github:ipfs/interop#refactor/streaming-pin-api", - "ipfsd-ctl": "^6.0.0", + "ipfsd-ctl": "^7.0.0", "iso-random-stream": "^1.1.1", "it-to-buffer": "^1.0.0", "nanoid": "^3.0.2", diff --git a/packages/ipfs/src/http/api/resources/files/cp.js b/packages/ipfs/src/http/api/resources/files/cp.js index b0a1a51e32..99e564f512 100644 --- a/packages/ipfs/src/http/api/resources/files/cp.js +++ b/packages/ipfs/src/http/api/resources/files/cp.js @@ -14,10 +14,7 @@ const mfsCp = { parents: Joi.boolean().default(false), flush: Joi.boolean().default(true), hashAlg: Joi.string().default('sha2-256'), - cidVersion: Joi.number().integer().valid([ - 0, - 1 - ]).default(0), + cidVersion: Joi.number().integer().valid(0, 1).default(0), shardSplitThreshold: Joi.number().integer().min(0).default(1000), timeout: Joi.timeout() }) diff --git a/packages/ipfs/src/http/api/resources/files/mkdir.js b/packages/ipfs/src/http/api/resources/files/mkdir.js index 2dbb0fec85..a0ae41c6ec 100644 --- a/packages/ipfs/src/http/api/resources/files/mkdir.js +++ b/packages/ipfs/src/http/api/resources/files/mkdir.js @@ -17,10 +17,7 @@ const mfsMkdir = { mtimeNsecs: Joi.number().integer().min(0), parents: Joi.boolean().default(false), hashAlg: Joi.string().default('sha2-256'), - cidVersion: Joi.number().integer().valid([ - 0, - 1 - ]).default(0), + cidVersion: Joi.number().integer().valid(0, 1).default(0), flush: Joi.boolean().default(true), shardSplitThreshold: Joi.number().integer().min(0).default(1000), timeout: Joi.timeout() diff --git a/packages/ipfs/src/http/api/resources/files/mv.js b/packages/ipfs/src/http/api/resources/files/mv.js index c68e93884b..028ed27067 100644 --- a/packages/ipfs/src/http/api/resources/files/mv.js +++ b/packages/ipfs/src/http/api/resources/files/mv.js @@ -14,10 +14,7 @@ const mfsMv = { recursive: Joi.boolean().default(false), parents: Joi.boolean().default(false), hashAlg: Joi.string().default('sha2-256'), - cidVersion: Joi.number().integer().valid([ - 0, - 1 - ]).default(0), + cidVersion: Joi.number().integer().valid(0, 1).default(0), flush: Joi.boolean().default(true), shardSplitThreshold: Joi.number().integer().min(0).default(1000), timeout: Joi.timeout() diff --git a/packages/ipfs/src/http/api/resources/files/touch.js b/packages/ipfs/src/http/api/resources/files/touch.js index 3a8a82daca..444576581a 100644 --- a/packages/ipfs/src/http/api/resources/files/touch.js +++ b/packages/ipfs/src/http/api/resources/files/touch.js @@ -15,10 +15,7 @@ const mfsTouch = { mtime: Joi.number().integer(), mtimeNsecs: Joi.number().integer().min(0), hashAlg: Joi.string().default('sha2-256'), - cidVersion: Joi.number().integer().valid([ - 0, - 1 - ]).default(0), + cidVersion: Joi.number().integer().valid(0, 1).default(0), flush: Joi.boolean().default(true), shardSplitThreshold: Joi.number().integer().min(0).default(1000), timeout: Joi.timeout() diff --git a/packages/ipfs/src/http/api/resources/files/write.js b/packages/ipfs/src/http/api/resources/files/write.js index 0103b7a476..60661b9e82 100644 --- a/packages/ipfs/src/http/api/resources/files/write.js +++ b/packages/ipfs/src/http/api/resources/files/write.js @@ -24,18 +24,11 @@ const mfsWrite = { create: Joi.boolean().default(false), truncate: Joi.boolean().default(false), rawLeaves: Joi.boolean().default(false), - cidVersion: Joi.number().integer().valid([ - 0, - 1 - ]).default(0), + cidVersion: Joi.number().integer().valid(0, 1).default(0), hashAlg: Joi.string().default('sha2-256'), parents: Joi.boolean().default(false), progress: Joi.func(), - strategy: Joi.string().valid([ - 'flat', - 'balanced', - 'trickle' - ]).default('trickle'), + strategy: Joi.string().valid('flat', 'balanced', 'trickle').default('trickle'), flush: Joi.boolean().default(true), reduceSingleLeafToSelf: Joi.boolean().default(false), shardSplitThreshold: Joi.number().integer().min(0).default(1000), diff --git a/packages/ipfs/src/http/error-handler.js b/packages/ipfs/src/http/error-handler.js index e1027211f1..f63e2e36b3 100644 --- a/packages/ipfs/src/http/error-handler.js +++ b/packages/ipfs/src/http/error-handler.js @@ -35,8 +35,8 @@ module.exports = server => { response: res.output.payload } - server.logger().error(debug) - server.logger().error(res) + server.logger.error(debug) + server.logger.error(res) } return h.response({ diff --git a/packages/ipfs/src/http/gateway/routes/gateway.js b/packages/ipfs/src/http/gateway/routes/gateway.js index 57d563aa6b..659758f2c8 100644 --- a/packages/ipfs/src/http/gateway/routes/gateway.js +++ b/packages/ipfs/src/http/gateway/routes/gateway.js @@ -1,6 +1,6 @@ 'use strict' -const Joi = require('@hapi/joi') +const Joi = require('joi') const resources = require('../resources') module.exports = [ @@ -10,9 +10,9 @@ module.exports = [ options: { handler: resources.gateway.handler, validate: { - params: { + params: Joi.object({ path: Joi.string().required() - } + }) }, response: { ranges: false // disable built-in support, handler does it manually @@ -28,9 +28,9 @@ module.exports = [ options: { handler: resources.gateway.handler, validate: { - params: { + params: Joi.object({ path: Joi.string().required() - } + }) }, response: { ranges: false // disable built-in support, handler does it manually diff --git a/packages/ipfs/src/http/index.js b/packages/ipfs/src/http/index.js index 9cc8c43422..ce35b3d3ce 100644 --- a/packages/ipfs/src/http/index.js +++ b/packages/ipfs/src/http/index.js @@ -74,7 +74,10 @@ class HttpApi { // CORS is enabled by default // TODO: shouldn't, fix this routes: { - cors: true + cors: true, + response: { + emptyStatusCode: 200 + } }, // Disable Compression // Why? Streaming compression in Hapi is not stable enough, @@ -171,7 +174,10 @@ class HttpApi { host, port, routes: { - cors: true + cors: true, + response: { + emptyStatusCode: 200 + } } }) server.app.ipfs = ipfs diff --git a/packages/ipfs/src/http/utils/joi.js b/packages/ipfs/src/http/utils/joi.js index 65e7f7c9fa..9353364dd4 100644 --- a/packages/ipfs/src/http/utils/joi.js +++ b/packages/ipfs/src/http/utils/joi.js @@ -1,6 +1,6 @@ 'use strict' -const Joi = require('@hapi/joi') +const Joi = require('joi') const CID = require('cids') const parseDuration = require('parse-duration').default const multiaddr = require('multiaddr') @@ -37,91 +37,104 @@ const toCID = (value) => { return new CID(value.toString().replace('/ipfs/', '')) } +const reqiureIfRequired = (value, helpers) => { + if (helpers.schema.$_getFlag('presence') === 'required' && !value) { + return { value, errors: helpers.error('required') } + } +} + module.exports = Joi .extend( (joi) => { return { - name: 'cid', + type: 'cid', base: joi.any(), - pre (value, state, options) { + validate: reqiureIfRequired, + coerce (value, helpers) { if (!value) { return } - return toCID(value) + return { value: toCID(value) } } } }, (joi) => { return { - name: 'ipfsPath', + type: 'ipfsPath', base: joi.string(), - coerce (value, state, options) { + validate: reqiureIfRequired, + coerce (value, helpers) { if (!value) { return } - return toIpfsPath(value) + return { value: toIpfsPath(value) } } } }, (joi) => { return { - name: 'peerId', + type: 'peerId', base: joi.string(), - pre (value, state, options) { + validate: reqiureIfRequired, + coerce (value, helpers) { if (!value) { return } - return new CID(value).toString() + return { value: new CID(value).toString() } } } }, (joi) => { return { - name: 'multiaddr', + type: 'multiaddr', base: joi.string(), - pre (value, state, options) { + validate: reqiureIfRequired, + coerce (value, helpers) { if (!value) { return } - return multiaddr(value).toString() + return { value: multiaddr(value).toString() } } } }, (joi) => { return { - name: 'timeout', - base: joi.string(), - pre (value, state, options) { + type: 'timeout', + base: joi.number(), + validate: reqiureIfRequired, + coerce (value, helpers) { if (!value) { return } - return parseDuration(value) + return { value: parseDuration(value) } } } }, (joi) => { return { - name: 'cidAndPath', + type: 'cidAndPath', base: joi.any(), - pre (value, state, options) { + validate: reqiureIfRequired, + coerce (value, helpers) { if (!value) { return } - return toCidAndPath(value) + return { value: toCidAndPath(value) } } } }, (joi) => { return { - name: 'cidBase', + type: 'cidBase', base: joi.string(), - pre (value, state, options) { + validate: reqiureIfRequired, + coerce (value, helpers) { if (!value) { return } @@ -130,20 +143,21 @@ module.exports = Joi throw new Error('Invalid base name') } - return value + return { value } } } }, (joi) => { return { - name: 'json', - base: joi.string(), - pre (value, state, options) { + type: 'json', + base: joi.any(), + validate: reqiureIfRequired, + coerce (value, helpers) { if (!value) { return } - return JSON.parse(value) + return { value: JSON.parse(value) } } } }) diff --git a/packages/ipfs/src/http/utils/multipart-request-parser.js b/packages/ipfs/src/http/utils/multipart-request-parser.js index f621cf85c8..00c52715a7 100644 --- a/packages/ipfs/src/http/utils/multipart-request-parser.js +++ b/packages/ipfs/src/http/utils/multipart-request-parser.js @@ -5,6 +5,7 @@ const multipart = require('it-multipart') const uint8ArrayConcat = require('uint8arrays/concat') const uint8ArrayToString = require('uint8arrays/to-string') const qs = require('querystring') +const drain = require('it-drain') const multipartFormdataType = 'multipart/form-data' const applicationDirectory = 'application/x-directory' @@ -41,12 +42,6 @@ const collect = async (stream) => { return uint8ArrayConcat(buffers, size) } -const ignore = async (stream) => { - for await (const _ of stream) { // eslint-disable-line no-unused-vars - - } -} - async function * parseEntry (stream, options) { for await (const part of stream) { if (!part.headers['content-type']) { @@ -113,7 +108,7 @@ async function * parser (stream, options) { mode: entry.mode } - await ignore(entry.body) + await drain(entry.body) } if (entry.type === 'symlink') { diff --git a/packages/ipfs/test/http-api/inject/block.js b/packages/ipfs/test/http-api/inject/block.js index 3379c43e60..69319eed3e 100644 --- a/packages/ipfs/test/http-api/inject/block.js +++ b/packages/ipfs/test/http-api/inject/block.js @@ -302,17 +302,11 @@ describe('/block', () => { }) it('should not stat a block for invalid cid-base option', async () => { - const form = new FormData() - form.append('data', Buffer.from('TEST' + Date.now())) - const headers = form.getHeaders() - - const payload = await streamToPromise(form) const res = await http({ method: 'POST', - url: '/api/v0/block/stat?cid-base=invalid', - headers, - payload + url: '/api/v0/block/stat?cid-base=invalid' }, { ipfs }) + expect(res).to.have.property('statusCode', 400) expect(res).to.have.nested.property('result.Message').that.includes('Invalid request query input') })