Skip to content

Commit 513fd9c

Browse files
authoredMar 24, 2023
fix!: encode/decode blockstore-s3 keys in base32upper (#201)
For consistency with blockstore-fs and to avoid problems with casing encode/decode all CID keys as base32upper BREAKING CHANGE: s3 filenames are now all base32upper
1 parent f85d719 commit 513fd9c

File tree

2 files changed

+17
-5
lines changed

2 files changed

+17
-5
lines changed
 

‎packages/blockstore-s3/src/index.ts

+15-3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import {
1414
ListObjectsV2Command
1515
} from '@aws-sdk/client-s3'
1616
import { CID } from 'multiformats/cid'
17+
import { base32upper } from 'multiformats/bases/base32'
18+
import type { MultibaseCodec } from 'multiformats/bases/interface'
1719

1820
export interface S3DatastoreInit {
1921
/**
@@ -31,6 +33,12 @@ export interface S3DatastoreInit {
3133
* Whether to try to create the bucket if it is missing when `.open` is called
3234
*/
3335
createIfMissing?: boolean
36+
37+
/**
38+
* The multibase codec to use - nb. should be case insensitive.
39+
* default: base32upper
40+
*/
41+
base?: MultibaseCodec<string>
3442
}
3543

3644
/**
@@ -41,6 +49,7 @@ export class S3Blockstore extends BaseBlockstore {
4149
public createIfMissing: boolean
4250
private readonly s3: S3
4351
private readonly bucket: string
52+
private readonly base: MultibaseCodec<string>
4453

4554
constructor (s3: S3, bucket: string, init?: S3DatastoreInit) {
4655
super()
@@ -57,14 +66,17 @@ export class S3Blockstore extends BaseBlockstore {
5766
this.s3 = s3
5867
this.bucket = bucket
5968
this.createIfMissing = init?.createIfMissing ?? false
69+
this.base = init?.base ?? base32upper
6070
}
6171

6272
/**
6373
* Returns the full key which includes the path to the ipfs store
6474
*/
65-
_getFullKey (key: CID): string {
75+
_getFullKey (cid: CID): string {
6676
// Avoid absolute paths with s3
67-
return [this.path, key.toString()].filter(Boolean).join('/').replace(/\/\/+/g, '/')
77+
const str = this.base.encoder.encode(cid.multihash.bytes)
78+
79+
return [this.path, str].filter(Boolean).join('/').replace(/\/\/+/g, '/')
6880
}
6981

7082
/**
@@ -212,7 +224,7 @@ export class S3Blockstore extends BaseBlockstore {
212224
}
213225

214226
// Remove the path from the key
215-
const cid = CID.parse(d.Key.slice((this.path ?? '').length))
227+
const cid = CID.decode(this.base.decoder.decode(d.Key.slice((this.path ?? '').length)))
216228

217229
yield {
218230
cid,

‎packages/blockstore-s3/test/index.spec.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ describe('S3Blockstore', () => {
5959
await store.put(cid, new TextEncoder().encode('test data'))
6060

6161
const command = await deferred.promise
62-
expect(command).to.have.nested.property('input.Key', '.ipfs/datastore/QmeimKZyjcBnuXmAD9zMnSjM9JodTbgGT3gutofkTqz9rE')
62+
expect(command).to.have.nested.property('input.Key', '.ipfs/datastore/BCIQPGZJ6QLZOFG3OP45NLMSJUWGJCO72QQKHLDTB6FXIB6BDSLRQYLY')
6363
})
6464

6565
it('should return a standard error when the put fails', async () => {
@@ -103,7 +103,7 @@ describe('S3Blockstore', () => {
103103
expect(value).to.equalBytes(buf)
104104

105105
const getObjectCommand = await deferred.promise
106-
expect(getObjectCommand).to.have.nested.property('input.Key', '.ipfs/datastore/QmeimKZyjcBnuXmAD9zMnSjM9JodTbgGT3gutofkTqz9rE')
106+
expect(getObjectCommand).to.have.nested.property('input.Key', '.ipfs/datastore/BCIQPGZJ6QLZOFG3OP45NLMSJUWGJCO72QQKHLDTB6FXIB6BDSLRQYLY')
107107
})
108108

109109
it('should return a standard not found error code if the key isn\'t found', async () => {

0 commit comments

Comments
 (0)
Please sign in to comment.