feat(api): public album info with locale fallback
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
// services/api/src/public/public.controller.ts —— /public 端点(Task 22 起步:
|
||||
// getPublicAlbum;Task 23 增补 listPublicPhotos / getPublicPhoto)。方法名与
|
||||
// 契约 operationId 一一对应。匿名访问(契约 security: []):
|
||||
// · 不挂 SessionGuard——控制器级守卫缺席即匿名,认证由持有 publicToken 本身
|
||||
// 取代(令牌不可枚举,持有链接者均可访问);
|
||||
// · 限流:P1a 不做(P2 引入点赞限流时统一评估公开面配额),此处记录约定。
|
||||
// 查询参数规整(limit 1..60 缺省 30、cursor 长度):非法 → 400
|
||||
// VALIDATION_FAILED;locale 取值不在此校验——契约规定不支持的语言按
|
||||
// defaultLocale 静默回退(Task 5 决策),语义在服务层。
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
HttpStatus,
|
||||
Param,
|
||||
Query,
|
||||
} from '@nestjs/common';
|
||||
import { ErrorCodes } from '@photo/contracts';
|
||||
import { ApiException } from '../api-exception';
|
||||
import {
|
||||
DEFAULT_PUBLIC_PHOTO_PAGE_SIZE,
|
||||
MAX_PUBLIC_PHOTO_PAGE_SIZE,
|
||||
type PublicAlbumResponse,
|
||||
PublicService,
|
||||
} from './public.service';
|
||||
|
||||
/** limit 查询参数:缺省 30,须为 1..60 的十进制整数(契约 bounds)。 */
|
||||
export function parsePublicPhotoLimit(raw: string | undefined): number {
|
||||
if (raw === undefined || raw === '') {
|
||||
return DEFAULT_PUBLIC_PHOTO_PAGE_SIZE;
|
||||
}
|
||||
if (!/^\d+$/.test(raw)) {
|
||||
throw new ApiException(
|
||||
ErrorCodes.VALIDATION_FAILED,
|
||||
'limit 必须是 1-60 的整数',
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
}
|
||||
const limit = Number.parseInt(raw, 10);
|
||||
if (limit < 1 || limit > MAX_PUBLIC_PHOTO_PAGE_SIZE) {
|
||||
throw new ApiException(
|
||||
ErrorCodes.VALIDATION_FAILED,
|
||||
'limit 必须是 1-60 的整数',
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
}
|
||||
return limit;
|
||||
}
|
||||
|
||||
@Controller('public/albums')
|
||||
export class PublicController {
|
||||
constructor(private readonly publicService: PublicService) {}
|
||||
|
||||
/** 公开相册信息:locale 缺省/非法/无条目均按 defaultLocale 回退(200)。 */
|
||||
@Get(':token')
|
||||
getPublicAlbum(
|
||||
@Param('token') token: string,
|
||||
@Query('locale') locale: string | undefined,
|
||||
): Promise<PublicAlbumResponse> {
|
||||
return this.publicService.getPublicAlbum(token, locale);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user