feat: Add texture rendering endpoints and service methods

- Introduced new API endpoints for rendering textures, avatars, capes, and previews, enhancing the texture handling capabilities.
- Implemented corresponding service methods in the TextureHandler to process rendering requests and return appropriate responses.
- Updated the TextureRenderService interface to include methods for rendering textures, avatars, and capes, along with their respective parameters.
- Enhanced error handling for invalid texture IDs and added support for different rendering types and formats.
- Updated go.mod to include the webp library for image processing.
This commit is contained in:
lan
2025-12-07 10:10:28 +08:00
parent 432c47d969
commit a51535a465
18 changed files with 984 additions and 24 deletions

View File

@@ -38,3 +38,9 @@ func MustGetJWTService() *JWTService {
}
return service
}

View File

@@ -63,3 +63,9 @@ func MustGetRustFSConfig() *RustFSConfig {
}

View File

@@ -99,3 +99,9 @@ func GetDSN(cfg config.DatabaseConfig) string {
cfg.Timezone,
)
}

View File

@@ -46,3 +46,9 @@ func MustGetService() *Service {

View File

@@ -49,3 +49,9 @@ func MustGetLogger() *zap.Logger {

View File

@@ -49,3 +49,9 @@ func MustGetClient() *Client {

View File

@@ -47,3 +47,9 @@ func MustGetClient() *StorageClient {

View File

@@ -173,18 +173,34 @@ func (s *StorageClient) GetObject(ctx context.Context, bucketName, objectName st
}
// ParseFileURL 从文件URL中解析出bucket和objectName
// URL格式: {publicURL}/{bucket}/{objectName}
// URL格式: {publicURL}/{bucket}/{objectName}[?query],自动忽略查询参数
func (s *StorageClient) ParseFileURL(fileURL string) (bucket, objectName string, err error) {
// 移除 publicURL 前缀
if !strings.HasPrefix(fileURL, s.publicURL) {
u, err := url.Parse(fileURL)
if err != nil {
return "", "", fmt.Errorf("URL解析失败: %w", err)
}
// 校验前缀(协议+主机+端口)
public, err := url.Parse(s.publicURL)
if err != nil {
return "", "", fmt.Errorf("publicURL解析失败: %w", err)
}
if u.Scheme != public.Scheme || u.Host != public.Host {
return "", "", fmt.Errorf("URL格式不正确必须以 %s 开头", s.publicURL)
}
// 移除 publicURL 前缀开头的 /
path := strings.TrimPrefix(fileURL, s.publicURL)
path = strings.TrimPrefix(path, "/")
// 去掉前缀开头的斜杠,仅使用路径部分,不包含 query
path := strings.TrimPrefix(u.Path, "/")
// 解析路径
// 如果 publicURL 自带路径前缀,移除该前缀
pubPath := strings.TrimPrefix(public.Path, "/")
if pubPath != "" {
if !strings.HasPrefix(path, pubPath) {
return "", "", fmt.Errorf("URL格式不正确缺少前缀 %s", public.Path)
}
path = strings.TrimPrefix(path, pubPath)
path = strings.TrimPrefix(path, "/")
}
parts := strings.SplitN(path, "/", 2)
if len(parts) < 2 {
return "", "", fmt.Errorf("URL格式不正确无法解析bucket和objectName")
@@ -194,8 +210,7 @@ func (s *StorageClient) ParseFileURL(fileURL string) (bucket, objectName string,
objectName = parts[1]
// URL解码 objectName
decoded, err := url.PathUnescape(objectName)
if err == nil {
if decoded, decErr := url.PathUnescape(objectName); decErr == nil {
objectName = decoded
}