training_data/packages/tus/src/handlers/HeadHandler.ts

91 lines
2.7 KiB
TypeScript
Raw Normal View History

2025-01-06 08:45:23 +08:00
/**
* HeadHandler
* TUS协议的HEAD请求
* 使使
*/
import { CancellationContext, ERRORS, Upload, Metadata } from '../utils'
import { BaseHandler } from './BaseHandler'
import type http from 'node:http'
/**
* HeadHandler类
* TUS协议的HEAD请求
* BaseHandler
* 使
* const handler = new HeadHandler(store, options)
* await handler.send(req, res, context)
*/
export class HeadHandler extends BaseHandler {
/**
* HEAD请求的核心方法
* @param req HTTP请求对象
* @param res HTTP响应对象
* @param context
* @returns HTTP响应
* @throws ERRORS.FILE_NOT_FOUND ID不存在时抛出
* @throws ERRORS.FILE_NO_LONGER_EXISTS
*/
async send(
req: http.IncomingMessage,
res: http.ServerResponse,
context: CancellationContext
) {
// 从请求中提取文件ID
const id = this.getFileIdFromRequest(req)
if (!id) {
throw ERRORS.FILE_NOT_FOUND
}
// 执行自定义的请求预处理逻辑
if (this.options.onIncomingRequest) {
await this.options.onIncomingRequest(req, res, id)
}
// 获取文件锁,防止并发操作
const lock = await this.acquireLock(req, id, context)
let file: Upload
try {
// 从存储中获取文件上传信息
file = await this.store.getUpload(id)
} finally {
// 无论成功与否,都释放锁
await lock.unlock()
}
// 检查文件是否已过期
const now = new Date()
if (
this.store.hasExtension('expiration') &&
this.store.getExpiration() > 0 &&
file.creation_date &&
now > new Date(new Date(file.creation_date).getTime() + this.store.getExpiration())
) {
throw ERRORS.FILE_NO_LONGER_EXISTS
}
// 设置响应头,防止缓存
res.setHeader('Cache-Control', 'no-store')
// 返回当前上传偏移量
res.setHeader('Upload-Offset', file.offset)
// 处理文件大小信息
if (file.sizeIsDeferred) {
// 如果文件大小未知,设置延迟长度标志
res.setHeader('Upload-Defer-Length', '1')
} else {
// 如果文件大小已知,返回实际大小
res.setHeader('Upload-Length', file.size as number)
}
// 处理文件元数据
if (file.metadata !== undefined) {
// 将元数据转换为字符串格式返回
res.setHeader('Upload-Metadata', Metadata.stringify(file.metadata) as string)
}
// 结束响应
return res.end()
}
}