完善部分内容

This commit is contained in:
dragon
2025-01-06 17:31:18 +08:00
parent 246bf13a6c
commit bb8966521c
5 changed files with 117 additions and 47 deletions

View File

@@ -2,8 +2,10 @@ package core
import ( import (
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"net/http" "net/http"
"os"
"time" "time"
"code.d7z.net/d7z-project/gitea-pages/pkg/utils" "code.d7z.net/d7z-project/gitea-pages/pkg/utils"
@@ -35,6 +37,9 @@ func (c *CacheBackend) Repos(owner string) (map[string]string, error) {
if err != nil { if err != nil {
ret, err = c.backend.Repos(owner) ret, err = c.backend.Repos(owner)
if err != nil { if err != nil {
if errors.Is(err, os.ErrNotExist) {
_ = c.config.Put(key, "{}", c.ttl)
}
return nil, err return nil, err
} }
data, err := json.Marshal(data) data, err := json.Marshal(data)
@@ -49,6 +54,9 @@ func (c *CacheBackend) Repos(owner string) (map[string]string, error) {
return nil, err return nil, err
} }
} }
if len(ret) == 0 {
return ret, os.ErrNotExist
}
return ret, nil return ret, nil
} }
@@ -59,6 +67,9 @@ func (c *CacheBackend) Branches(owner, repo string) (map[string]string, error) {
if err != nil { if err != nil {
ret, err = c.backend.Branches(owner, repo) ret, err = c.backend.Branches(owner, repo)
if err != nil { if err != nil {
if errors.Is(err, os.ErrNotExist) {
_ = c.config.Put(key, "{}", c.ttl)
}
return nil, err return nil, err
} }
data, err := json.Marshal(data) data, err := json.Marshal(data)
@@ -73,6 +84,9 @@ func (c *CacheBackend) Branches(owner, repo string) (map[string]string, error) {
return nil, err return nil, err
} }
} }
if len(ret) == 0 {
return ret, os.ErrNotExist
}
return ret, nil return ret, nil
} }

View File

@@ -14,83 +14,108 @@ import (
) )
type ServerMeta struct { type ServerMeta struct {
client *http.Client client *http.Client
backend Backend Backend
cache utils.Config cache utils.Config
ttl time.Duration ttl time.Duration
locker *utils.Locker
} }
type PageMeta struct { type PageMeta struct {
CommitID string `json:"commit_id"` // 提交 COMMIT ID CommitID string `json:"id"` // 提交 COMMIT ID
IsPage bool `json:"is_page"` // 是否为 Page IsPage bool `json:"pg"` // 是否为 Page
Domain string `json:"domain"` // 匹配的域名和路径 Domain string `json:"dm"` // 匹配的域名
HistoryRouteMode bool `json:"route_history"` // 路由模式 HistoryRouteMode bool `json:"rt"` // 路由模式
CustomNotFound bool `json:"404"` // 注册了自定义 404 页面
}
func (m *PageMeta) From(data string) error {
return json.Unmarshal([]byte(data), m)
}
func (m *PageMeta) String() string {
marshal, _ := json.Marshal(m)
return string(marshal)
} }
func NewServerMeta(client *http.Client, backend Backend, config utils.Config, ttl time.Duration) *ServerMeta { func NewServerMeta(client *http.Client, backend Backend, config utils.Config, ttl time.Duration) *ServerMeta {
return &ServerMeta{client, backend, config, ttl} return &ServerMeta{client, backend, config, ttl, utils.NewLocker()}
} }
func (s *ServerMeta) Meta(owner, repo, branch string) (*PageMeta, error) { func (s *ServerMeta) GetMeta(owner, repo, branch string) (*PageMeta, error) {
rel := &PageMeta{ rel := &PageMeta{
IsPage: false, IsPage: false,
} }
key := fmt.Sprintf("meta/%s/%s/%s", owner, repo, branch) if repos, err := s.Repos(owner); err != nil {
pushMeta := func() error { return nil, err
data, err := json.Marshal(rel) } else {
if err != nil { defBranch := repos[repo]
return err if defBranch == "" {
return nil, os.ErrNotExist
}
if branch == "" {
branch = defBranch
}
}
if branches, err := s.Branches(owner, repo); err != nil {
return nil, err
} else {
rel.CommitID = branches[branch]
if rel.CommitID == "" {
return nil, os.ErrNotExist
} }
return s.cache.Put(key, string(data), s.ttl)
} }
key := fmt.Sprintf("meta/%s/%s/%s", owner, repo, branch)
cache, err := s.cache.Get(key) cache, err := s.cache.Get(key)
if err != nil { if err != nil && !errors.Is(err, os.ErrNotExist) {
if !errors.Is(err, os.ErrNotExist) { return nil, err
return nil, err }
} if err == nil {
} else { if err = rel.From(cache); err == nil {
if err = json.Unmarshal([]byte(cache), rel); err == nil { if !rel.IsPage {
return nil, os.ErrNotExist
}
return rel, nil return rel, nil
} }
} }
repos, err := s.backend.Repos(owner) mux := s.locker.Open(key)
if err != nil { mux.Lock()
return nil, err defer mux.Unlock()
} cache, err = s.cache.Get(key)
rel.CommitID = repos[repo] if err == nil {
if rel.CommitID == "" { if err = rel.From(cache); err == nil {
_ = pushMeta() if !rel.IsPage {
return nil, os.ErrNotExist return nil, os.ErrNotExist
} }
if branch != "" { return rel, nil
branches, err := s.backend.Branches(owner, repo)
if err != nil {
return nil, err
} }
rel.CommitID = branches[branch]
} }
if rel.CommitID == "" {
_ = pushMeta() if find, _ := s.FileExists(owner, repo, rel.CommitID, "index.html"); !find {
rel.IsPage = false
_ = s.cache.Put(key, rel.String(), s.ttl)
return nil, os.ErrNotExist return nil, os.ErrNotExist
} }
if find, _ := s.FileExists(owner, repo, rel.CommitID, "404.html"); !find {
rel.CustomNotFound = true
}
if cname, err := s.ReadString(owner, repo, rel.CommitID, "CNAME"); err != nil && !errors.Is(err, os.ErrNotExist) { if cname, err := s.ReadString(owner, repo, rel.CommitID, "CNAME"); err != nil && !errors.Is(err, os.ErrNotExist) {
return nil, err return nil, err
} else { } else {
rel.Domain = strings.TrimSpace(cname) rel.Domain = strings.TrimSpace(cname)
} }
if find, _ := s.FileExists(owner, repo, rel.CommitID, "index.html"); find { if find, _ := s.FileExists(owner, repo, rel.CommitID, ".history"); find {
rel.IsPage = true
}
if find, _ := s.FileExists(owner, repo, rel.CommitID, ".history-mode"); find {
rel.HistoryRouteMode = true rel.HistoryRouteMode = true
} }
_ = pushMeta() _ = s.cache.Put(key, rel.String(), s.ttl)
return rel, nil return rel, nil
} }
func (s *ServerMeta) ReadString(owner, repo, branch, path string) (string, error) { func (s *ServerMeta) ReadString(owner, repo, branch, path string) (string, error) {
resp, err := s.backend.Open(s.client, owner, repo, branch, path, nil) resp, err := s.Open(s.client, owner, repo, branch, path, nil)
if err != nil { if err != nil {
return "", err return "", err
} }
@@ -106,7 +131,7 @@ func (s *ServerMeta) ReadString(owner, repo, branch, path string) (string, error
} }
func (s *ServerMeta) FileExists(owner, repo, branch, path string) (bool, error) { func (s *ServerMeta) FileExists(owner, repo, branch, path string) (bool, error) {
resp, err := s.backend.Open(s.client, owner, repo, branch, path, nil) resp, err := s.Open(s.client, owner, repo, branch, path, nil)
if err != nil { if err != nil {
return false, err return false, err
} }

9
pkg/core/page.go Normal file
View File

@@ -0,0 +1,9 @@
package core
type PageContent struct {
meta PageMeta
}
func (p *PageContent) GetMeta(domain, path string) (*PageMeta, error) {
}

View File

@@ -15,6 +15,8 @@ type ServerOptions struct {
Cache utils.Cache Cache utils.Cache
MaxCacheSize int MaxCacheSize int
HttpClient *http.Client
} }
func DefaultOptions(domain string) ServerOptions { func DefaultOptions(domain string) ServerOptions {
@@ -24,22 +26,25 @@ func DefaultOptions(domain string) ServerOptions {
Config: configMemory, Config: configMemory,
Cache: utils.NewCacheMemory(1024*1024*10, int(memory.FreeMemory()/3*2)), Cache: utils.NewCacheMemory(1024*1024*10, int(memory.FreeMemory()/3*2)),
MaxCacheSize: 1024 * 1024 * 10, MaxCacheSize: 1024 * 1024 * 10,
HttpClient: http.DefaultClient,
} }
} }
type Server struct { type Server struct {
backend core.Backend meta *core.ServerMeta
options *ServerOptions options *ServerOptions
} }
func NewPageServer(backend core.Backend, options ServerOptions) *Server { func NewPageServer(backend core.Backend, options ServerOptions) *Server {
backend = core.NewCacheBackend(backend, options.Config, time.Minute)
return &Server{ return &Server{
backend: core.NewCacheBackend(backend, options.Config, time.Minute), meta: core.NewServerMeta(options.HttpClient, backend, options.Config, time.Minute),
options: &options, options: &options,
} }
} }
func (s *Server) ServeHTTP(writer http.ResponseWriter, request *http.Request) { func (s *Server) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
} }
func (s *Server) Close() error { func (s *Server) Close() error {

17
pkg/utils/locker.go Normal file
View File

@@ -0,0 +1,17 @@
package utils
import "sync"
type Locker struct {
sy sync.Map
}
func NewLocker() *Locker {
return &Locker{
sy: sync.Map{},
}
}
func (l *Locker) Open(key string) *sync.Mutex {
actual, _ := l.sy.LoadOrStore(key, &sync.Mutex{})
return actual.(*sync.Mutex)
}