Skip to content

Commit 268f21c

Browse files
为 filter 添加全局配置支持
1 parent f4ca137 commit 268f21c

File tree

15 files changed

+338
-283
lines changed

15 files changed

+338
-283
lines changed

cmd/local/main.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,18 @@ func main() {
5656
if err != nil {
5757
zap.L().Fatal("failed to init memory provider", zap.Error(err))
5858
}
59-
server := pkg.NewPageServer(http.DefaultClient,
59+
server, err := pkg.NewPageServer(http.DefaultClient,
6060
provider, domain, "gh-pages", memory, memory, 0, &nopCache{},
6161
func(w http.ResponseWriter, r *http.Request, err error) {
6262
if errors.Is(err, os.ErrNotExist) {
6363
http.Error(w, "page not found.", http.StatusNotFound)
6464
} else if err != nil {
6565
http.Error(w, err.Error(), http.StatusInternalServerError)
6666
}
67-
})
67+
}, make(map[string]map[string]any))
68+
if err != nil {
69+
zap.L().Fatal("failed to init page", zap.Error(err))
70+
}
6871
err = http.ListenAndServe(port, server)
6972
if err != nil && !errors.Is(err, http.ErrServerClosed) {
7073
zap.L().Fatal("failed to start server", zap.Error(err))

cmd/server/config.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,10 @@ type Config struct {
2929

3030
Page ConfigPage `yaml:"page"` // 页面配置
3131

32-
Render ConfigRender `yaml:"render"` // 渲染配置
33-
Proxy ConfigProxy `yaml:"proxy"` // 反向代理配置
34-
3532
StaticDir string `yaml:"static"` // 静态资源提供路径
3633

34+
Filters map[string]map[string]any `yaml:"filters"` // 渲染器配置
35+
3736
pageErrNotFound, pageErrUnknown *template.Template
3837
}
3938

cmd/server/main.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func main() {
6464
if !ok {
6565
log.Fatalln(errors.New("database not support cursor"))
6666
}
67-
pageServer := pkg.NewPageServer(
67+
pageServer, err := pkg.NewPageServer(
6868
http.DefaultClient,
6969
backend,
7070
config.Domain,
@@ -74,7 +74,11 @@ func main() {
7474
config.Cache.MetaTTL,
7575
cacheBlob.Child("filter"),
7676
config.ErrorHandler,
77+
config.Filters,
7778
)
79+
if err != nil {
80+
log.Fatalln(err)
81+
}
7882
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT)
7983
defer stop()
8084

pkg/core/filter.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@ type FilterContext struct {
2222
RepoDB kv.CursorPagedKV
2323
}
2424

25-
type FilterParams map[string]any
25+
type Params map[string]any
2626

27-
func (f FilterParams) String() string {
27+
func (f Params) String() string {
2828
marshal, _ := json.Marshal(f)
2929
return strings.ReplaceAll(string(marshal), "\"", "'")
3030
}
3131

32-
func (f FilterParams) Unmarshal(target any) error {
32+
func (f Params) Unmarshal(target any) error {
3333
marshal, err := json.Marshal(f)
3434
if err != nil {
3535
return err
@@ -38,9 +38,9 @@ func (f FilterParams) Unmarshal(target any) error {
3838
}
3939

4040
type Filter struct {
41-
Path string `json:"path"`
42-
Type string `json:"type"`
43-
Params FilterParams `json:"params"`
41+
Path string `json:"path"`
42+
Type string `json:"type"`
43+
Params Params `json:"params"`
4444
}
4545

4646
func NextCallWrapper(call FilterCall, parentCall NextCall, stack Filter) NextCall {
@@ -69,4 +69,7 @@ type FilterCall func(
6969
next NextCall,
7070
) error
7171

72-
type FilterInstance func(config FilterParams) (FilterCall, error)
72+
type (
73+
GlobalFilter func(config Params) (FilterInstance, error)
74+
FilterInstance func(route Params) (FilterCall, error)
75+
)

pkg/filters/block.go

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,27 @@ import (
66
"gopkg.d7z.net/gitea-pages/pkg/core"
77
)
88

9-
var FilterInstBlock core.FilterInstance = func(config core.FilterParams) (core.FilterCall, error) {
10-
var param struct {
11-
Code int `json:"code"`
12-
Message string `json:"message"`
13-
}
14-
if err := config.Unmarshal(&param); nil != err {
15-
return nil, err
16-
}
17-
if param.Code == 0 {
18-
param.Code = http.StatusForbidden
19-
}
20-
if param.Message == "" {
21-
param.Message = http.StatusText(param.Code)
22-
}
23-
return func(ctx core.FilterContext, writer http.ResponseWriter, request *http.Request, next core.NextCall) error {
24-
writer.WriteHeader(param.Code)
25-
if param.Message != "" {
26-
_, _ = writer.Write([]byte(param.Message))
9+
func FilterInstBlock(_ core.Params) (core.FilterInstance, error) {
10+
return func(config core.Params) (core.FilterCall, error) {
11+
var param struct {
12+
Code int `json:"code"`
13+
Message string `json:"message"`
2714
}
28-
return nil
15+
if err := config.Unmarshal(&param); nil != err {
16+
return nil, err
17+
}
18+
if param.Code == 0 {
19+
param.Code = http.StatusForbidden
20+
}
21+
if param.Message == "" {
22+
param.Message = http.StatusText(param.Code)
23+
}
24+
return func(ctx core.FilterContext, writer http.ResponseWriter, request *http.Request, next core.NextCall) error {
25+
writer.WriteHeader(param.Code)
26+
if param.Message != "" {
27+
_, _ = writer.Write([]byte(param.Message))
28+
}
29+
return nil
30+
}, nil
2931
}, nil
3032
}

pkg/filters/common.go

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
package filters
22

33
import (
4+
"errors"
5+
6+
"go.uber.org/zap"
47
"gopkg.d7z.net/gitea-pages/pkg/core"
58
"gopkg.d7z.net/gitea-pages/pkg/filters/goja"
69
)
710

8-
func DefaultFilters() map[string]core.FilterInstance {
9-
return map[string]core.FilterInstance{
11+
func DefaultFilters(config map[string]map[string]any) (map[string]core.FilterInstance, error) {
12+
if config == nil {
13+
return nil, errors.New("config is nil")
14+
}
15+
result := make(map[string]core.FilterInstance)
16+
for key, instance := range map[string]core.GlobalFilter{
1017
"block": FilterInstBlock,
1118
"redirect": FilterInstRedirect,
1219
"direct": FilterInstDirect,
@@ -15,5 +22,20 @@ func DefaultFilters() map[string]core.FilterInstance {
1522
"failback": FilterInstFailback,
1623
"template": FilterInstTemplate,
1724
"js": goja.FilterInstGoJa,
25+
} {
26+
item, ok := config[key]
27+
if !ok {
28+
item = make(map[string]any)
29+
}
30+
if item["_disable"] == true {
31+
zap.L().Debug("skip filter", zap.String("key", key))
32+
continue
33+
}
34+
inst, err := instance(item)
35+
if err != nil {
36+
return nil, err
37+
}
38+
result[key] = inst
1839
}
40+
return result, nil
1941
}

pkg/filters/default.go

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,27 @@ import (
99
"gopkg.d7z.net/gitea-pages/pkg/core"
1010
)
1111

12-
var FilterInstDefaultNotFound core.FilterInstance = func(config core.FilterParams) (core.FilterCall, error) {
13-
return func(ctx core.FilterContext, writer http.ResponseWriter, request *http.Request, next core.NextCall) error {
14-
err := next(ctx, writer, request)
15-
if err != nil && errors.Is(err, os.ErrNotExist) {
16-
open, err := ctx.NativeOpen(ctx, "/404.html", nil)
17-
if open != nil {
18-
defer open.Body.Close()
12+
func FilterInstDefaultNotFound(_ core.Params) (core.FilterInstance, error) {
13+
return func(config core.Params) (core.FilterCall, error) {
14+
return func(ctx core.FilterContext, writer http.ResponseWriter, request *http.Request, next core.NextCall) error {
15+
err := next(ctx, writer, request)
16+
if err != nil && errors.Is(err, os.ErrNotExist) {
17+
open, err := ctx.NativeOpen(ctx, "/404.html", nil)
18+
if open != nil {
19+
defer open.Body.Close()
20+
}
21+
if err != nil {
22+
return err
23+
}
24+
writer.Header().Set("Content-Type", "text/html; charset=utf-8")
25+
if l := open.Header.Get("Content-Length"); l != "" {
26+
writer.Header().Set("Content-Length", l)
27+
}
28+
writer.WriteHeader(http.StatusNotFound)
29+
_, _ = io.Copy(writer, open.Body)
30+
return nil
1931
}
20-
if err != nil {
21-
return err
22-
}
23-
writer.Header().Set("Content-Type", "text/html; charset=utf-8")
24-
if l := open.Header.Get("Content-Length"); l != "" {
25-
writer.Header().Set("Content-Length", l)
26-
}
27-
writer.WriteHeader(http.StatusNotFound)
28-
_, _ = io.Copy(writer, open.Body)
29-
return nil
30-
}
31-
return err
32+
return err
33+
}, nil
3234
}, nil
3335
}

pkg/filters/direct.go

Lines changed: 50 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -14,59 +14,61 @@ import (
1414
"gopkg.d7z.net/gitea-pages/pkg/core"
1515
)
1616

17-
var FilterInstDirect core.FilterInstance = func(config core.FilterParams) (core.FilterCall, error) {
18-
var param struct {
19-
Prefix string `json:"prefix"`
20-
}
21-
if err := config.Unmarshal(&param); err != nil {
22-
return nil, err
23-
}
24-
param.Prefix = strings.Trim(param.Prefix, "/") + "/"
25-
return func(ctx core.FilterContext, writer http.ResponseWriter, request *http.Request, next core.NextCall) error {
26-
err := next(ctx, writer, request)
27-
if (err != nil && !errors.Is(err, os.ErrNotExist)) || err == nil {
28-
return err
17+
func FilterInstDirect(_ core.Params) (core.FilterInstance, error) {
18+
return func(config core.Params) (core.FilterCall, error) {
19+
var param struct {
20+
Prefix string `json:"prefix"`
2921
}
30-
if request.Method != http.MethodHead && request.Method != http.MethodGet {
31-
http.Error(writer, "Method not allowed", http.StatusMethodNotAllowed)
32-
return nil
22+
if err := config.Unmarshal(&param); err != nil {
23+
return nil, err
3324
}
34-
var resp *http.Response
35-
var path string
36-
defaultPath := param.Prefix + strings.TrimSuffix(ctx.Path, "/")
37-
for _, p := range []string{defaultPath, defaultPath + "/index.html"} {
38-
zap.L().Debug("direct fetch", zap.String("path", p))
39-
resp, err = ctx.NativeOpen(request.Context(), p, nil)
40-
if err != nil {
41-
if resp != nil {
42-
resp.Body.Close()
43-
}
44-
if !errors.Is(err, os.ErrNotExist) {
45-
zap.L().Debug("error", zap.Any("error", err))
46-
return err
25+
param.Prefix = strings.Trim(param.Prefix, "/") + "/"
26+
return func(ctx core.FilterContext, writer http.ResponseWriter, request *http.Request, next core.NextCall) error {
27+
err := next(ctx, writer, request)
28+
if (err != nil && !errors.Is(err, os.ErrNotExist)) || err == nil {
29+
return err
30+
}
31+
if request.Method != http.MethodHead && request.Method != http.MethodGet {
32+
http.Error(writer, "Method not allowed", http.StatusMethodNotAllowed)
33+
return nil
34+
}
35+
var resp *http.Response
36+
var path string
37+
defaultPath := param.Prefix + strings.TrimSuffix(ctx.Path, "/")
38+
for _, p := range []string{defaultPath, defaultPath + "/index.html"} {
39+
zap.L().Debug("direct fetch", zap.String("path", p))
40+
resp, err = ctx.NativeOpen(request.Context(), p, nil)
41+
if err != nil {
42+
if resp != nil {
43+
resp.Body.Close()
44+
}
45+
if !errors.Is(err, os.ErrNotExist) {
46+
zap.L().Debug("error", zap.Any("error", err))
47+
return err
48+
}
49+
continue
4750
}
48-
continue
51+
path = p
52+
break
53+
}
54+
if resp == nil {
55+
return os.ErrNotExist
56+
}
57+
defer resp.Body.Close()
58+
if err != nil {
59+
return err
4960
}
50-
path = p
51-
break
52-
}
53-
if resp == nil {
54-
return os.ErrNotExist
55-
}
56-
defer resp.Body.Close()
57-
if err != nil {
58-
return err
59-
}
6061

61-
writer.Header().Set("Content-Type", mime.TypeByExtension(filepath.Ext(path)))
62-
lastMod, err := time.Parse(http.TimeFormat, resp.Header.Get("Last-Modified"))
63-
if err == nil {
64-
if seeker, ok := resp.Body.(io.ReadSeeker); ok {
65-
http.ServeContent(writer, request, filepath.Base(path), lastMod, seeker)
66-
return nil
62+
writer.Header().Set("Content-Type", mime.TypeByExtension(filepath.Ext(path)))
63+
lastMod, err := time.Parse(http.TimeFormat, resp.Header.Get("Last-Modified"))
64+
if err == nil {
65+
if seeker, ok := resp.Body.(io.ReadSeeker); ok {
66+
http.ServeContent(writer, request, filepath.Base(path), lastMod, seeker)
67+
return nil
68+
}
6769
}
68-
}
69-
_, err = io.Copy(writer, resp.Body)
70-
return err
70+
_, err = io.Copy(writer, resp.Body)
71+
return err
72+
}, nil
7173
}, nil
7274
}

0 commit comments

Comments
 (0)