-
Notifications
You must be signed in to change notification settings - Fork 2.3k
/
Copy pathstaticHandler.ts
71 lines (60 loc) · 2.3 KB
/
staticHandler.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import type { Storage } from '@google-cloud/storage'
import type { StaticHandler } from '@payloadcms/plugin-cloud-storage/types'
import type { CollectionConfig } from 'payload'
import { getFilePrefix } from '@payloadcms/plugin-cloud-storage/utilities'
import path from 'path'
interface Args {
bucket: string
collection: CollectionConfig
getStorageClient: () => Storage
}
export const getHandler = ({ bucket, collection, getStorageClient }: Args): StaticHandler => {
return async (req, { headers: incomingHeaders, params: { clientUploadContext, filename } }) => {
try {
const prefix = await getFilePrefix({ clientUploadContext, collection, filename, req })
const file = getStorageClient().bucket(bucket).file(path.posix.join(prefix, filename))
const [metadata] = await file.getMetadata()
const etagFromHeaders = req.headers.get('etag') || req.headers.get('if-none-match')
const objectEtag = metadata.etag
let headers = new Headers(incomingHeaders)
headers.append('Content-Length', String(metadata.size))
headers.append('Content-Type', String(metadata.contentType))
headers.append('ETag', String(metadata.etag))
if (
collection.upload &&
typeof collection.upload === 'object' &&
typeof collection.upload.modifyResponseHeaders === 'function'
) {
headers = collection.upload.modifyResponseHeaders({ headers }) || headers
}
if (etagFromHeaders && etagFromHeaders === objectEtag) {
return new Response(null, {
headers,
status: 304,
})
}
// Manually create a ReadableStream for the web from a Node.js stream.
const readableStream = new ReadableStream({
start(controller) {
const nodeStream = file.createReadStream()
nodeStream.on('data', (chunk) => {
controller.enqueue(new Uint8Array(chunk))
})
nodeStream.on('end', () => {
controller.close()
})
nodeStream.on('error', (err) => {
controller.error(err)
})
},
})
return new Response(readableStream, {
headers,
status: 200,
})
} catch (err: unknown) {
req.payload.logger.error(err)
return new Response('Internal Server Error', { status: 500 })
}
}
}