mirror of
https://github.com/GopeedLab/gopeed.git
synced 2026-11-09 01:50:30 +00:00
feat: move native communication to FFI (#1457)
This commit is contained in:
86 files changed
+4558
-886
No files matched your search
@@ -0,0 +1,94 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
pathpkg "path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type HandlerFunc func(*Context) *Response
|
||||
|
||||
type RouteSpec struct {
|
||||
Method string
|
||||
Pattern string
|
||||
Handler HandlerFunc
|
||||
parts []routePart
|
||||
}
|
||||
|
||||
type routePart struct {
|
||||
literal string
|
||||
param string
|
||||
}
|
||||
|
||||
func newRoute(method, pattern string, handler HandlerFunc) RouteSpec {
|
||||
pattern = cleanPath(pattern)
|
||||
return RouteSpec{
|
||||
Method: strings.ToUpper(method),
|
||||
Pattern: pattern,
|
||||
Handler: handler,
|
||||
parts: parseRouteParts(pattern),
|
||||
}
|
||||
}
|
||||
|
||||
func validateRoutes(routes []RouteSpec) error {
|
||||
patterns := make(map[string]struct{}, len(routes))
|
||||
for _, route := range routes {
|
||||
if route.Method == "" || route.Pattern == "" || route.Handler == nil {
|
||||
return fmt.Errorf("invalid API route: %+v", route)
|
||||
}
|
||||
key := route.Method + " " + route.Pattern
|
||||
if _, exists := patterns[key]; exists {
|
||||
return fmt.Errorf("duplicate API route: %s", key)
|
||||
}
|
||||
patterns[key] = struct{}{}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseRouteParts(pattern string) []routePart {
|
||||
pattern = strings.Trim(pattern, "/")
|
||||
if pattern == "" {
|
||||
return nil
|
||||
}
|
||||
segments := strings.Split(pattern, "/")
|
||||
parts := make([]routePart, 0, len(segments))
|
||||
for _, segment := range segments {
|
||||
if strings.HasPrefix(segment, "{") && strings.HasSuffix(segment, "}") {
|
||||
name := strings.TrimSuffix(strings.TrimPrefix(segment, "{"), "}")
|
||||
parts = append(parts, routePart{param: name})
|
||||
continue
|
||||
}
|
||||
parts = append(parts, routePart{literal: segment})
|
||||
}
|
||||
return parts
|
||||
}
|
||||
|
||||
func (r RouteSpec) Match(rawPath string) (map[string]string, bool) {
|
||||
path := strings.Trim(cleanPath(rawPath), "/")
|
||||
if path == "" && len(r.parts) == 0 {
|
||||
return map[string]string{}, true
|
||||
}
|
||||
segments := strings.Split(path, "/")
|
||||
if len(segments) != len(r.parts) {
|
||||
return nil, false
|
||||
}
|
||||
params := make(map[string]string)
|
||||
for index, part := range r.parts {
|
||||
if part.param != "" {
|
||||
params[part.param] = segments[index]
|
||||
continue
|
||||
}
|
||||
if part.literal != segments[index] {
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
return params, true
|
||||
}
|
||||
|
||||
func cleanPath(rawPath string) string {
|
||||
clean := pathpkg.Clean("/" + strings.TrimSpace(rawPath))
|
||||
if clean == "." {
|
||||
return "/"
|
||||
}
|
||||
return clean
|
||||
}
|
||||
Reference in new issue
Block a user