Skip to content

Commit 9a7a415

Browse files
fix: blobs & cors issue (#145)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent e79a30a commit 9a7a415

File tree

9 files changed

+38
-18
lines changed

9 files changed

+38
-18
lines changed

docs/content/1.docs/2.storage/3.blob.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ It can used to handle file uploads in API routes.
238238
```ts [server/api/blob.put.ts]
239239
export default eventHandler(async (event) => {
240240
return hubBlob().handleUpload(event, {
241-
formKey: 'file', // read file or files form the `formKey` field of request body (body should be a `FormData` object)
241+
formKey: 'files', // read file or files form the `formKey` field of request body (body should be a `FormData` object)
242242
multiple: true, // when `true`, the `formKey` field will be an array of `Blob` objects
243243
contentType: ['image/jpeg', 'images/png'], // allowed types of the file
244244
})
@@ -264,7 +264,7 @@ async function onFileSelect(event: Event) {
264264
265265
::field-group
266266
::field{name="formKey" type="string"}
267-
The form key to read the file from. Defaults to `'file'`.
267+
The form key to read the file from. Defaults to `'files'`.
268268
::
269269
::field{name="multiple" type="boolean"}
270270
When `true`, the `formKey` field will be an array of `Blob` objects.
@@ -578,7 +578,7 @@ async function onFileSelect({ target }: Event) {
578578
::field{name="options" type="Object" required}
579579
Optionally, you can pass Fetch options to the request. Read more about Fetch API [here](https://developer.mozilla.org/en-US/docs/Web/API/fetch#options).
580580
::field{name="formKey" type="string"}
581-
The key to add the file/files to the request form. Defaults to `'file'`.
581+
The key to add the file/files to the request form. Defaults to `'files'`.
582582
::
583583
::field{name="multiple" type="boolean"}
584584
Whether to allow multiple files to be uploaded. Defaults to `true`.

playground/server/api/blob/index.put.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
export default eventHandler(async (event) => {
22
const { prefix } = getQuery(event)
33
return hubBlob().handleUpload(event, {
4-
formKey: 'file', // default
4+
formKey: 'files', // default
55
multiple: true, // default
66
prefix: String(prefix || '')
77
})

src/module.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { mkdir, writeFile, readFile } from 'node:fs/promises'
22
import { execSync } from 'node:child_process'
33
import { argv } from 'node:process'
4-
import { defineNuxtModule, createResolver, logger, addServerScanDir, installModule, addServerImportsDir, addImportsDir } from '@nuxt/kit'
4+
import { defineNuxtModule, createResolver, logger, addServerScanDir, installModule, addServerImportsDir, addImportsDir, addServerHandler } from '@nuxt/kit'
55
import { join } from 'pathe'
66
import { defu } from 'defu'
77
import { findWorkspaceDir } from 'pkg-types'
@@ -155,6 +155,14 @@ export default defineNuxtModule<ModuleOptions>({
155155
})
156156
}
157157

158+
if (nuxt.options.dev) {
159+
addServerHandler({
160+
route: '/api/_hub',
161+
middleware: true,
162+
handler: resolve('./runtime/cors.dev')
163+
})
164+
}
165+
158166
// Fallback to custom placeholder when openAPI is disabled
159167
nuxt.options.alias['#hub/openapi'] = nuxt.options.nitro?.experimental?.openAPI === true
160168
? '#internal/nitro/routes/openapi'

src/runtime/compsables/useUpload.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { BlobObject } from '../server/utils/blob'
44
interface UploadOptions extends FetchOptions {
55
/**
66
* The key to add the file/files to the request form.
7-
* @default 'file'
7+
* @default 'files'
88
*/
99
formKey?: string
1010

@@ -18,7 +18,7 @@ interface UploadOptions extends FetchOptions {
1818
export function useUpload(apiBase: string, options: UploadOptions & { multiple: false }): (data: FileList | HTMLInputElement | File[] | File) => Promise<BlobObject>
1919
export function useUpload(apiBase: string, options: UploadOptions): ((data: File) => Promise<BlobObject>) & ((data: FileList | HTMLInputElement | File[]) => Promise<BlobObject[]>)
2020
export function useUpload(apiBase: string, options: UploadOptions = {}) {
21-
const { formKey = 'file', multiple = true, method, ...fetchOptions } = options || {}
21+
const { formKey = 'files', multiple = true, method, ...fetchOptions } = options || {}
2222

2323
async function upload(data: File): Promise<BlobObject>
2424
async function upload(data: FileList | HTMLInputElement | File[] | File): Promise<BlobObject[] | BlobObject> {

src/runtime/cors.dev.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { handleCors, eventHandler } from 'h3'
2+
3+
export default eventHandler((event) => {
4+
// add cors for devtools embed
5+
handleCors(event, {
6+
methods: '*',
7+
origin: [
8+
'https://admin.hub.nuxt.com'
9+
]
10+
})
11+
})

src/runtime/server/api/_hub/blob/head/[...pathname].get.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
import { eventHandler, getValidatedRouterParams } from 'h3'
22
import { z } from 'zod'
33
import { hubBlob } from '../../../../utils/blob'
4+
import { requireNuxtHubAuthorization } from '../../../../utils/auth'
5+
import { requireNuxtHubFeature } from '../../../../utils/features'
46

57
export default eventHandler(async (event) => {
8+
await requireNuxtHubAuthorization(event)
9+
requireNuxtHubFeature('blob')
10+
611
const { pathname } = await getValidatedRouterParams(event, z.object({
712
pathname: z.string().min(1)
813
}).parse)

src/runtime/server/api/_hub/blob/index.post.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import { eventHandler, getQuery } from 'h3'
22
import { hubBlob } from '../../../utils/blob'
33
import { requireNuxtHubAuthorization } from '../../../utils/auth'
4+
import { requireNuxtHubFeature } from '../../../utils/features'
45

56
export default eventHandler(async (event) => {
67
await requireNuxtHubAuthorization(event)
8+
requireNuxtHubFeature('blob')
9+
710
const query = getQuery(event)
811

912
return hubBlob().handleUpload(event, {

src/runtime/server/utils/auth.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,12 @@
11
import type { H3Event } from 'h3'
2-
import { getHeader, createError, handleCors } from 'h3'
2+
import { getHeader, createError } from 'h3'
33
import { $fetch } from 'ofetch'
44

55
const localCache: Map<string, boolean> = new Map()
66

77
export async function requireNuxtHubAuthorization(event: H3Event) {
88
// Skip if in development
99
if (import.meta.dev) {
10-
// add cors for devtools embed
11-
handleCors(event, {
12-
methods: '*',
13-
origin: [
14-
'https://admin.hub.nuxt.com'
15-
]
16-
})
1710
return
1811
}
1912

src/runtime/server/utils/blob.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ export type HandleMPUResponse =
149149
export interface BlobUploadOptions extends BlobPutOptions, BlobValidateOptions {
150150
/**
151151
* The key to get the file/files from the request form.
152-
* @default 'file'
152+
* @default 'files'
153153
*/
154154
formKey?: string
155155
/**
@@ -393,10 +393,10 @@ export function hubBlob(): HubBlob {
393393
return mapR2MpuToBlobMpu(mpu)
394394
},
395395
async handleUpload(event: H3Event, options: BlobUploadOptions = {}) {
396-
const opts = { formKey: 'file', multiple: true, ...options } as BlobUploadOptions
396+
const opts = { formKey: 'files', multiple: true, ...options } as BlobUploadOptions
397397

398398
const form = await readFormData(event)
399-
const files = form.getAll(opts.formKey || 'file') as File[]
399+
const files = form.getAll(opts.formKey || 'files') as File[]
400400
if (!files) {
401401
throw createError({ statusCode: 400, message: 'Missing files' })
402402
}

0 commit comments

Comments
 (0)