110 lines
2.9 KiB
Go
110 lines
2.9 KiB
Go
package utils
|
||
|
||
import (
|
||
"fmt"
|
||
"path/filepath"
|
||
"strconv"
|
||
"strings"
|
||
|
||
"github.com/PuerkitoBio/purell"
|
||
)
|
||
|
||
// PathSegment slug 优先,空则回退数字 id。
|
||
func PathSegment(slug string, id int64) string {
|
||
if s := strings.TrimSpace(slug); s != "" {
|
||
return s
|
||
}
|
||
if id > 0 {
|
||
return strconv.FormatInt(id, 10)
|
||
}
|
||
return ""
|
||
}
|
||
|
||
// PathInfo 路径信息
|
||
type PathInfo struct {
|
||
Dir string // 目录
|
||
Ext string // 扩展名
|
||
Filename string // 没有扩展名的文件名名称
|
||
FullFileName string // 文件全名
|
||
}
|
||
|
||
// PathForInfo 解析路径
|
||
// 返回文件,路径,文件名等信息
|
||
func PathForInfo(path string) (pi PathInfo) {
|
||
if path == "" {
|
||
return
|
||
}
|
||
ext := filepath.Ext(path)
|
||
dir, name := filepath.Split(path)
|
||
|
||
pi.Dir = dir
|
||
pi.Ext = ext
|
||
pi.Filename = strings.TrimRight(name, ext)
|
||
pi.FullFileName = name
|
||
return
|
||
}
|
||
|
||
// JoinUrlPath 域名与uri拼接(走 purell 标准化,会剥掉尾部斜杠)。
|
||
// 适用于 CDN 文件链接(m3u8 分段、vtt、静态图等)这类"不需要尾部斜杠"的场景。
|
||
// 需要保留尾部斜杠的页面 URL(sitemap/rss/indexnow)请使用 JoinUrlPathKeepSlash。
|
||
func JoinUrlPath(host string, uri string) (urlpath string) {
|
||
urlpath = joinRawUrlPath(host, uri)
|
||
if urlpath == "" {
|
||
return
|
||
}
|
||
// 标准化 URL
|
||
normalized, err := purell.NormalizeURLString(urlpath, purell.FlagsUsuallySafeGreedy)
|
||
if err != nil {
|
||
return urlpath
|
||
}
|
||
return normalized
|
||
}
|
||
|
||
// JoinUrlPathKeepSlash 域名与uri拼接,保留 uri 原始的尾部斜杠,不做任何标准化。
|
||
// sitemap/rss/indexnow 的页面 URL 必须与路由注册的 /archives/:id/ 等完全一致,
|
||
// 否则爬虫每次访问都会被 gin 的 RedirectTrailingSlash 301 到带 / 的地址,
|
||
// 浪费抓取预算并造成重定向链。
|
||
func JoinUrlPathKeepSlash(host string, uri string) string {
|
||
return joinRawUrlPath(host, uri)
|
||
}
|
||
|
||
// JoinUrlPathAppendEnd 域名与uri拼接 追加/结尾
|
||
func JoinUrlPathAppendEnd(host string, uri string) (urlpath string) {
|
||
if uri == "" {
|
||
return
|
||
}
|
||
switch {
|
||
case strings.HasSuffix(host, "/") && strings.HasPrefix(uri, "/"):
|
||
urlpath = host[0:len(host)-1] + uri
|
||
case !strings.HasSuffix(host, "/") && !strings.HasPrefix(uri, "/"):
|
||
urlpath = host + "/" + uri
|
||
default:
|
||
urlpath = host + uri
|
||
}
|
||
// 标准化 URL
|
||
normalized, err := purell.NormalizeURLString(urlpath, purell.FlagsUsuallySafeGreedy)
|
||
if err != nil {
|
||
return urlpath
|
||
}
|
||
if !strings.HasSuffix(normalized, "/") {
|
||
normalized = fmt.Sprintf("%s/", normalized)
|
||
}
|
||
return normalized
|
||
}
|
||
|
||
// joinRawUrlPath 纯拼接,不做任何标准化。
|
||
func joinRawUrlPath(host string, uri string) (urlpath string) {
|
||
if uri == "" {
|
||
return
|
||
}
|
||
switch {
|
||
case strings.HasSuffix(host, "/") && strings.HasPrefix(uri, "/"):
|
||
urlpath = host[0:len(host)-1] + uri
|
||
case !strings.HasSuffix(host, "/") && !strings.HasPrefix(uri, "/"):
|
||
urlpath = host + "/" + uri
|
||
default:
|
||
urlpath = host + uri
|
||
}
|
||
return
|
||
}
|