From cdc40b753adb9f4610e37beb3d52291c517f0eab Mon Sep 17 00:00:00 2001 From: Vincent Voyer Date: Thu, 12 Sep 2024 11:26:53 +0200 Subject: [PATCH] also implement in copy --- packages/blob/src/api.ts | 6 ++++++ packages/blob/src/copy.ts | 8 +++++++- packages/blob/src/index.node.test.ts | 19 ++++++++++++------- packages/blob/src/put-helpers.ts | 7 +------ 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/packages/blob/src/api.ts b/packages/blob/src/api.ts index 30df81808..7d5f62c60 100644 --- a/packages/blob/src/api.ts +++ b/packages/blob/src/api.ts @@ -5,6 +5,12 @@ import { debug } from './debug'; import type { BlobCommandOptions } from './helpers'; import { BlobError, getTokenFromOptionsOrEnv } from './helpers'; +// maximum pathname length is: +// 1024 (provider limit) - 26 chars (vercel internal suffixes) - 31 chars (blob `-randomId` suffix) = 967 +// we round it to 950 to make it more human friendly, and we apply the limit whatever the value of +// addRandomSuffix is, to make it consistent +export const MAXIMUM_PATHNAME_LENGTH = 950; + export class BlobAccessError extends BlobError { constructor() { super('Access denied, please provide a valid token for this resource.'); diff --git a/packages/blob/src/copy.ts b/packages/blob/src/copy.ts index ac3e55e5e..4669daed9 100644 --- a/packages/blob/src/copy.ts +++ b/packages/blob/src/copy.ts @@ -1,4 +1,4 @@ -import { requestApi } from './api'; +import { MAXIMUM_PATHNAME_LENGTH, requestApi } from './api'; import type { CommonCreateBlobOptions } from './helpers'; import { BlobError } from './helpers'; @@ -35,6 +35,12 @@ export async function copy( throw new BlobError('access must be "public"'); } + if (toPathname.length > MAXIMUM_PATHNAME_LENGTH) { + throw new BlobError( + `pathname is too long, maximum length is ${MAXIMUM_PATHNAME_LENGTH}`, + ); + } + const headers: Record = {}; if (options.addRandomSuffix !== undefined) { diff --git a/packages/blob/src/index.node.test.ts b/packages/blob/src/index.node.test.ts index d4d2a8d7b..815c2b987 100644 --- a/packages/blob/src/index.node.test.ts +++ b/packages/blob/src/index.node.test.ts @@ -577,13 +577,6 @@ describe('blob client', () => { }); it('throws when filepath is too long', async () => { - mockClient - .intercept({ - path: () => true, - method: 'PUT', - }) - .reply(200, mockedFileMetaPut); - await expect( put('a'.repeat(951), 'Test Body', { access: 'public', @@ -718,4 +711,16 @@ describe('blob client', () => { ); }); }); + + describe('copy', () => { + it('throws when filepath is too long', async () => { + await expect( + copy('source', 'a'.repeat(951), { + access: 'public', + }), + ).rejects.toThrow( + new Error('Vercel Blob: pathname is too long, maximum length is 950'), + ); + }); + }); }); diff --git a/packages/blob/src/put-helpers.ts b/packages/blob/src/put-helpers.ts index d3321cd46..afbd57da3 100644 --- a/packages/blob/src/put-helpers.ts +++ b/packages/blob/src/put-helpers.ts @@ -3,6 +3,7 @@ import type { Readable } from 'stream'; import type { ClientCommonCreateBlobOptions } from './client'; import type { CommonCreateBlobOptions } from './helpers'; import { BlobError } from './helpers'; +import { MAXIMUM_PATHNAME_LENGTH } from './api'; const putOptionHeaderMap = { cacheControlMaxAge: 'x-cache-control-max-age', @@ -68,12 +69,6 @@ export function createPutHeaders( return headers; } -// maximum pathname length is: -// 1024 (provider limit) - 26 chars (vercel internal suffixes) - 31 chars (blob `-randomId` suffix) = 967 -// we round it to 950 to make it more human friendly, and we apply the limit whatever the value of -// addRandomSuffix is, to make it consistent -const MAXIMUM_PATHNAME_LENGTH = 950; - export async function createPutOptions< TOptions extends CommonPutCommandOptions, >({