Skip to content

Commit

Permalink
Merge branch 'main' into feature/custom-error-message-in-retrieveClie…
Browse files Browse the repository at this point in the history
…ntToken
  • Loading branch information
daryl-cecile committed Nov 19, 2023
2 parents 96fe921 + 8e06689 commit e16d78c
Show file tree
Hide file tree
Showing 10 changed files with 110 additions and 6 deletions.
10 changes: 10 additions & 0 deletions packages/blob/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# @vercel/blob

## 0.15.1

### Patch Changes

- f9c4061: fix(blob): Enforce content-type on fetch requests during token generation

Before this change, we would not send the content-type header on fetch requests sent to your server during client uploads. We consider this a bugfix as it should have been sent before.

⚠️ If you upgrade to this version, and you're using any smart request body parser (like Next.js Pages API routes) then: You need to remove any `JSON.parse(request.body)` at the `handleUpload` step, as the body will be JSON by default now. This is valid for the `onBeforeGenerateToken` and `onUploadCompleted` steps.

## 0.15.0

### Minor Changes
Expand Down
3 changes: 3 additions & 0 deletions packages/blob/jest/setup.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// TextEncoder and TextDecoder are not defined in Jest dom environment,
// but they are available everywhere else.
// See https://stackoverflow.com/questions/68468203/why-am-i-getting-textencoder-is-not-defined-in-jest
const { TextEncoder, TextDecoder } = require('node:util');

Object.assign(global, { TextDecoder, TextEncoder });
7 changes: 5 additions & 2 deletions packages/blob/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@vercel/blob",
"version": "0.15.0",
"version": "0.15.1",
"description": "The Vercel Blob JavaScript API client",
"homepage": "https://vercel.com/storage/blob",
"repository": {
Expand Down Expand Up @@ -53,7 +53,10 @@
},
"jest": {
"preset": "ts-jest",
"testEnvironment": "node"
"testEnvironment": "node",
"testEnvironmentOptions": {
"url": "http://localhost:3000"
}
},
"dependencies": {
"jest-environment-jsdom": "29.7.0",
Expand Down
77 changes: 77 additions & 0 deletions packages/blob/src/client.browser.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import undici from 'undici';
import { upload } from './client';

// can't use undici mocking utilities because jsdom does not support performance.markResourceTiming
jest.mock('undici', () => ({
fetch: jest
.fn()
.mockResolvedValueOnce({
status: 200,
ok: true,
json: () =>
Promise.resolve({
type: 'blob.generate-client-token',
clientToken: 'fake-token-for-test',
}),
})
.mockResolvedValueOnce({
status: 200,
ok: true,
json: () =>
Promise.resolve({
url: `https://storeId.public.blob.vercel-storage.com/superfoo.txt`,
pathname: 'foo.txt',
contentType: 'text/plain',
contentDisposition: 'attachment; filename="foo.txt"',
}),
}),
}));

describe('upload()', () => {
beforeEach(() => {
process.env.BLOB_READ_WRITE_TOKEN =
'vercel_blob_rw_12345fakeStoreId_30FakeRandomCharacters12345678';
jest.clearAllMocks();
});

it('should upload a file from the client', async () => {
await expect(
upload('foo.txt', 'Test file data', {
access: 'public',
handleUploadUrl: '/api/upload',
}),
).resolves.toMatchInlineSnapshot(`
{
"contentDisposition": "attachment; filename="foo.txt"",
"contentType": "text/plain",
"pathname": "foo.txt",
"url": "https://storeId.public.blob.vercel-storage.com/superfoo.txt",
}
`);

const fetchMock = undici.fetch as jest.Mock;
expect(fetchMock).toHaveBeenCalledTimes(2);
expect(fetchMock).toHaveBeenNthCalledWith(
1,
'http://localhost:3000/api/upload',
{
body: '{"type":"blob.generate-client-token","payload":{"pathname":"foo.txt","callbackUrl":"http://localhost:3000/api/upload"}}',
headers: { 'content-type': 'application/json' },
method: 'POST',
},
);
expect(fetchMock).toHaveBeenNthCalledWith(
2,
'https://blob.vercel-storage.com/foo.txt',
{
body: 'Test file data',
duplex: 'half',
headers: {
authorization: 'Bearer fake-token-for-test',
'x-api-version': '5',
},
method: 'PUT',
},
);
});
});
3 changes: 3 additions & 0 deletions packages/blob/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,9 @@ async function retrieveClientToken(options: {
const res = await fetch(url, {
method: 'POST',
body: JSON.stringify(event),
headers: {
'content-type': 'application/json',
},
});

if (!res.ok) {
Expand Down
2 changes: 1 addition & 1 deletion packages/blob/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ export async function validateBlobApiResponse(
// This version is used to ensure that the client and server are compatible
// The server (Vercel Blob API) uses this information to change its behavior like the
// response format
const BLOB_API_VERSION = 4;
const BLOB_API_VERSION = 5;

export function getApiVersionHeader(): { 'x-api-version'?: string } {
let versionOverride = null;
Expand Down
1 change: 1 addition & 0 deletions packages/blob/src/index.browser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { put } from './index';

const BLOB_STORE_BASE_URL = 'https://storeId.public.blob.vercel-storage.com';

// Can't use the usual undici mocking utilities because they don't work with jsdom environment
jest.mock('undici', () => ({
fetch: (): unknown =>
Promise.resolve({
Expand Down
7 changes: 7 additions & 0 deletions test/next/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# vercel-storage-integration-test-suite

## 0.1.34

### Patch Changes

- Updated dependencies [f9c4061]
- @vercel/blob@0.15.1

## 0.1.33

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion test/next/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vercel-storage-integration-test-suite",
"version": "0.1.33",
"version": "0.1.34",
"private": true,
"scripts": {
"build": "next build",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ export default async function handleBody(
return;
}

const body = request.body as string;
const body = request.body as HandleUploadBody;
try {
const jsonResponse = await handleUpload({
body: JSON.parse(body) as HandleUploadBody,
body,
request,
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/require-await -- [@vercel/style-guide@5 migration]
onBeforeGenerateToken: async (pathname) => {
Expand Down

0 comments on commit e16d78c

Please sign in to comment.