Files
cloudpods/pkg/apigateway/handler/dispatcher.go
2023-07-09 07:37:34 +08:00

123 lines
2.9 KiB
Go

// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package handler
import (
"context"
"fmt"
"net/http"
"path"
"strings"
"time"
"yunion.io/x/onecloud/pkg/appsrv"
)
type handleFunc func(context.Context, http.ResponseWriter, *http.Request)
type SHandler struct {
Method string
Prefix string
MiddlewareFunc appsrv.MiddlewareFunc
HandleFunc handleFunc
}
func NewHandler(method string, mf appsrv.MiddlewareFunc, hf handleFunc, paths ...string) SHandler {
h := SHandler{
Method: method,
MiddlewareFunc: mf,
HandleFunc: hf,
}
h.Prefix = path.Join(paths...)
return h
}
func (h SHandler) indexKey() string {
return fmt.Sprintf("%s-%s", h.Method, h.Prefix)
}
func (h SHandler) Bind(app *appsrv.Application) {
f := h.HandleFunc
if h.MiddlewareFunc != nil {
f = h.MiddlewareFunc(f)
}
segs := appsrv.SplitPath(h.Prefix)
hi := appsrv.NewHandlerInfo(h.Method, segs, f, nil, "", nil)
if h.Method == "GET" {
hi.SetProcessTimeoutCallback(func(hdr *appsrv.SHandlerInfo, r *http.Request) time.Duration {
if len(r.URL.Query().Get("export_keys")) > 0 ||
r.URL.Query().Has("force_no_paging") ||
strings.HasSuffix(r.URL.Path, "/splitable-export") {
return time.Hour * 2
}
return -time.Second
})
}
app.AddHandler3(hi)
}
func NewMethodHandlerFactory(method string, mf appsrv.MiddlewareFunc, prefix string) func(handleFunc, ...string) SHandler {
return func(hf handleFunc, paths ...string) SHandler {
pPaths := []string{prefix}
pPaths = append(pPaths, paths...)
return NewHandler(method, mf, hf, pPaths...)
}
}
type SHandlers struct {
prefix string
handlers map[string]SHandler
}
func NewHandlers(prefix string) *SHandlers {
return &SHandlers{
prefix: prefix,
handlers: make(map[string]SHandler),
}
}
type HandlerPath struct {
f handleFunc
paths []string
}
func (f *SHandlers) GetPrefix() string {
return f.prefix
}
func (f *SHandlers) AddByMethod(method string, mf appsrv.MiddlewareFunc, hs ...HandlerPath) *SHandlers {
newH := NewMethodHandlerFactory(method, mf, f.prefix)
for _, h := range hs {
hd := newH(h.f, h.paths...)
idx := hd.indexKey()
f.handlers[idx] = hd
}
return f
}
func (f *SHandlers) Bind(app *appsrv.Application) {
for _, h := range f.handlers {
h.Bind(app)
}
}
func NewHP(f handleFunc, paths ...string) HandlerPath {
return HandlerPath{f, paths}
}
type IHandler interface {
Bind(*appsrv.Application)
}