ConusAI vendor v0.1.0-dev.20261013+85463d22
This commit is contained in:
parent
c3c6526952
commit
0da8a2a81b
@@ -0,0 +1,37 @@
|
||||
import 'server-only'
|
||||
import { fileId, fileRepository } from '@/entities/file'
|
||||
import { blob, db } from '@/shared/api'
|
||||
import { currentVisitor } from '@/shared/lib/visitor-session'
|
||||
|
||||
function notFound(): Response {
|
||||
return new Response('not found', { status: 404 })
|
||||
}
|
||||
|
||||
/**
|
||||
* The bytes of one attachment, for the visitor who attached it. The platform's
|
||||
* blob URL needs the deployment token, which the browser does not have, so the
|
||||
* app downloads server-side and streams the bytes back. Anything that is not
|
||||
* the visitor's own attachment answers 404, never 403.
|
||||
*/
|
||||
export async function downloadAttachment(id: string): Promise<Response> {
|
||||
const parsed = fileId.safeParse(id)
|
||||
if (!parsed.success) return notFound()
|
||||
const visitor = await currentVisitor()
|
||||
if (!visitor) return notFound()
|
||||
const file = await fileRepository(db()).get(parsed.data, visitor)
|
||||
if (!file) return notFound()
|
||||
const upstream = await blob().download(file.url)
|
||||
if (!upstream.body) return notFound()
|
||||
return new Response(upstream.body, {
|
||||
headers: {
|
||||
'content-type': file.contentType,
|
||||
// RFC 5987: the name is percent-encoded, so quotes and CR/LF cannot inject.
|
||||
'content-disposition': `attachment; filename*=UTF-8''${encodeURIComponent(file.name)}`,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/** `GET /files/<id>`: the route handler the app router re-exports. */
|
||||
export async function GET(_request: Request, context: { params: Promise<{ id: string }> }): Promise<Response> {
|
||||
return downloadAttachment((await context.params).id)
|
||||
}
|
||||
Reference in New Issue
Block a user