143 lines
4.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package handler
import (
"net/http"
"net/url"
"path"
"strconv"
"strings"
"webp_server_go/config"
"webp_server_go/encoder"
"webp_server_go/helper"
"github.com/gofiber/fiber/v2"
log "github.com/sirupsen/logrus"
)
func Convert(c *fiber.Ctx) error {
// 检查是否为根路径
if c.Path() == "/" {
return c.SendString("Welcome to CZL WebP Server")
}
var (
reqHostname = c.Hostname()
reqHeader = &c.Request().Header
reqURIRaw, _ = url.QueryUnescape(c.Path())
reqURIwithQueryRaw, _ = url.QueryUnescape(c.OriginalURL())
reqURI = path.Clean(reqURIRaw)
reqURIwithQuery = path.Clean(reqURIwithQueryRaw)
filename = path.Base(reqURI)
realRemoteAddr = ""
targetHostName = ""
targetHost = ""
width, _ = strconv.Atoi(c.Query("width"))
height, _ = strconv.Atoi(c.Query("height"))
maxHeight, _ = strconv.Atoi(c.Query("max_height"))
maxWidth, _ = strconv.Atoi(c.Query("max_width"))
extraParams = config.ExtraParams{
Width: width,
Height: height,
MaxWidth: maxWidth,
MaxHeight: maxHeight,
}
)
log.Debugf("Incoming connection from %s %s %s", c.IP(), reqHostname, reqURIwithQuery)
// 检查路径是否匹配 IMG_MAP 中的任何前缀
var matchedPrefix string
var matchedTarget string
for prefix, target := range config.Config.ImageMap {
if strings.HasPrefix(reqURI, prefix) {
matchedPrefix = prefix
matchedTarget = target
break
}
}
// 如果不匹配任何 IMG_MAP 前缀,直接返回 404
if matchedPrefix == "" {
log.Warnf("请求的路径不匹配任何配置的 IMG_MAP: %s", c.Path())
return c.SendStatus(fiber.StatusNotFound)
}
// 设置目标主机信息
targetUrl, _ := url.Parse(matchedTarget)
targetHostName = targetUrl.Host
targetHost = targetUrl.Scheme + "://" + targetUrl.Host
// 调整请求 URI
reqURI = strings.Replace(reqURI, matchedPrefix, targetUrl.Path, 1)
reqURIwithQuery = strings.Replace(reqURIwithQuery, matchedPrefix, targetUrl.Path, 1)
// 构造远程地址
realRemoteAddr = targetHost + reqURIwithQuery
// 处理非图片文件
if !helper.IsImageFile(filename) {
log.Infof("Non-image file requested: %s", reqURI)
log.Infof("Redirecting to: %s", realRemoteAddr)
return c.Redirect(realRemoteAddr, fiber.StatusFound)
}
// 检查允许的文件类型
if !helper.CheckAllowedType(filename) {
msg := "不允许的文件扩展名 " + filename
log.Warn(msg)
return c.Status(http.StatusBadRequest).SendString(msg)
}
// 获取远程图像元数据
metadata := fetchRemoteImg(realRemoteAddr, targetHostName)
rawImageAbs := path.Join(config.Config.RemoteRawPath, targetHostName, metadata.Id)
// 后续的图像处理逻辑
supportedFormats := helper.GuessSupportedFormat(reqHeader)
// 检查原始图像是否存在
if !helper.ImageExists(rawImageAbs) {
helper.DeleteMetadata(reqURIwithQuery, targetHostName)
msg := "Image not found!"
log.Warn(msg)
return c.Status(404).SendString(msg)
}
// 检查文件大小
isSmall, err := helper.IsFileSizeSmall(rawImageAbs, 100*1024) // 100KB
if err != nil {
log.Errorf("检查文件大小时出错: %v", err)
return c.SendStatus(fiber.StatusInternalServerError)
}
if isSmall {
log.Infof("文件 %s 小于100KB跳过转换", rawImageAbs)
return c.SendFile(rawImageAbs)
}
avifAbs, webpAbs, jxlAbs := helper.GenOptimizedAbsPath(metadata, targetHostName)
// 根据支持的格式和配置进行转换
encoder.ConvertFilter(rawImageAbs, jxlAbs, avifAbs, webpAbs, extraParams, supportedFormats, nil)
var availableFiles = []string{rawImageAbs}
if supportedFormats["avif"] {
availableFiles = append(availableFiles, avifAbs)
}
if supportedFormats["webp"] {
availableFiles = append(availableFiles, webpAbs)
}
if supportedFormats["jxl"] {
availableFiles = append(availableFiles, jxlAbs)
}
finalFilename := helper.FindSmallestFiles(availableFiles)
contentType := helper.GetFileContentType(finalFilename)
c.Set("Content-Type", contentType)
c.Set("X-Compression-Rate", helper.GetCompressionRate(rawImageAbs, finalFilename))
return c.SendFile(finalFilename)
}