-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: send blobs when running ipfs-http-client in the browser (#3184)
To support streaming of native types with no buffering, normalise add input to blobs and upload using native FormData when the http client is run in the browser. That is, if the user passes a blob to the http client in the browser leave it alone as enumerating blob contents cause the file data to be read. Browser FormData objects do not allow you to specify headers for each multipart part which means we can't pass UnixFS metadata via the headers so we turn the metadata into a querystring and append it to the field name for each multipart part as a workaround. Fixes #3138 BREAKING CHANGES: - Removes the `mode`, `mtime` and `mtime-nsec` headers from multipart requests - Passes `mode`, `mtime` and `mtime-nsec` as querystring parameters appended to the field name of multipart requests
- Loading branch information
1 parent
b44dd1a
commit 6b0bbc1
Showing
6 changed files
with
112 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
'use strict' | ||
|
||
const normaliseInput = require('ipfs-core-utils/src/files/normalise-input') | ||
const modeToString = require('./mode-to-string') | ||
const mtimeToObject = require('./mtime-to-object') | ||
const { File, FormData } = require('ipfs-utils/src/globalthis') | ||
|
||
async function multipartRequest (source = '', abortController, headers = {}) { | ||
const formData = new FormData() | ||
let index = 0 | ||
|
||
for await (const { content, path, mode, mtime } of normaliseInput(source)) { | ||
let fileSuffix = '' | ||
const type = content ? 'file' : 'dir' | ||
|
||
if (index > 0) { | ||
fileSuffix = `-${index}` | ||
} | ||
|
||
let fieldName = type + fileSuffix | ||
const qs = [] | ||
|
||
if (mode !== null && mode !== undefined) { | ||
qs.push(`mode=${modeToString(mode)}`) | ||
} | ||
|
||
if (mtime != null) { | ||
const { | ||
secs, nsecs | ||
} = mtimeToObject(mtime) | ||
|
||
qs.push(`mtime=${secs}`) | ||
|
||
if (nsecs != null) { | ||
qs.push(`mtime-nsecs=${nsecs}`) | ||
} | ||
} | ||
|
||
if (qs.length) { | ||
fieldName = `${fieldName}?${qs.join('&')}` | ||
} | ||
|
||
if (content) { | ||
formData.set(fieldName, content, encodeURIComponent(path)) | ||
} else { | ||
formData.set(fieldName, new File([''], encodeURIComponent(path), { type: 'application/x-directory' })) | ||
} | ||
|
||
index++ | ||
} | ||
|
||
return { | ||
headers, | ||
body: formData | ||
} | ||
} | ||
|
||
module.exports = multipartRequest |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/* eslint-env mocha */ | ||
|
||
'use strict' | ||
|
||
const { Buffer } = require('buffer') | ||
const { expect } = require('interface-ipfs-core/src/utils/mocha') | ||
const f = require('./utils/factory')() | ||
|
||
describe('.add', function () { | ||
this.timeout(20 * 1000) | ||
|
||
let ipfs | ||
|
||
before(async function () { | ||
ipfs = (await f.spawn()).api | ||
}) | ||
|
||
after(() => f.clean()) | ||
|
||
it('should ignore metadata until https://github.com/ipfs/go-ipfs/issues/6920 is implemented', async () => { | ||
const data = Buffer.from('some data') | ||
const result = await ipfs.add(data, { | ||
mode: 0o600, | ||
mtime: { | ||
secs: 1000, | ||
nsecs: 0 | ||
} | ||
}) | ||
|
||
expect(result).to.not.have.property('mode') | ||
expect(result).to.not.have.property('mtime') | ||
expect(result).to.have.property('cid') | ||
|
||
const { cid } = result | ||
expect(cid).to.have.property('codec', 'dag-pb') | ||
expect(cid.toString()).to.equal('QmVv4Wz46JaZJeH5PMV4LGbRiiMKEmszPYY3g6fjGnVXBS') | ||
}) | ||
}) |