]> 127.0.0.1 Git - part/.git/commitdiff
Improve v0.22.4
authorqydysky <32743305+qydysky@users.noreply.github.com>
Wed, 8 Feb 2023 18:44:59 +0000 (02:44 +0800)
committerqydysky <32743305+qydysky@users.noreply.github.com>
Wed, 8 Feb 2023 18:44:59 +0000 (02:44 +0800)
web/Web.go
web/Web_test.go

index 4831e55dbb5ade7f3c098644b65776cb84cf13f3..a467c63b1df051cb65c91244b85ea40626793be8 100644 (file)
@@ -2,6 +2,7 @@ package part
 
 import (
        "context"
+       "fmt"
        "net/http"
        "strconv"
        "sync"
@@ -13,32 +14,131 @@ import (
 type Web struct {
        Server *http.Server
        mux    *http.ServeMux
-       wrs    sync.Map
-       mode   string
 }
 
-func New(conf *http.Server) (o *Web) {
-
-       o = new(Web)
+type WebSync struct {
+       Server *http.Server
+       mux    *http.ServeMux
+       wrs    *WebPath
+}
 
-       o.mode = "simple"
-       o.Server = conf
+type WebPath struct {
+       path  string
+       f     func(w http.ResponseWriter, r *http.Request)
+       sameP *WebPath
+       next  *WebPath
+       l     sync.RWMutex
+}
 
-       if o.Server.Handler == nil {
-               o.mux = http.NewServeMux()
-               o.Server.Handler = o.mux
+func (t *WebPath) Load(path string) (func(w http.ResponseWriter, r *http.Request), bool) {
+       fmt.Println("l", t.path, path)
+       t.l.RLock()
+       if t.path == "" {
+               t.l.RUnlock()
+               return nil, false
+       } else if t.path == path {
+               t.l.RUnlock()
+               return t.f, true
+       } else if len(path) > len(t.path) && path[:len(t.path)] == t.path {
+               if t.path == "/" || path[len(t.path)] == '/' {
+                       fmt.Println("-")
+                       if t.sameP != nil {
+                               if f, ok := t.sameP.Load(path); ok {
+                                       t.l.RUnlock()
+                                       return f, true
+                               } else {
+                                       t.l.RUnlock()
+                                       return t.f, true
+                               }
+                       } else {
+                               t.l.RUnlock()
+                               return t.f, true
+                       }
+               } else {
+                       if t.next != nil {
+                               t.l.RUnlock()
+                               return t.next.Load(path)
+                       } else {
+                               t.l.RUnlock()
+                               return nil, false
+                       }
+               }
+       } else if t.next != nil {
+               t.l.RUnlock()
+               return t.next.Load(path)
+       } else {
+               t.l.RUnlock()
+               return nil, false
        }
+}
 
-       go o.Server.ListenAndServe()
-
-       return
+func (t *WebPath) Store(path string, f func(w http.ResponseWriter, r *http.Request)) {
+       t.l.RLock()
+       if t.path == path || t.path == "" {
+               t.l.RUnlock()
+               t.l.Lock()
+               t.path = path
+               t.f = f
+               t.l.Unlock()
+       } else if len(path) > len(t.path) && path[:len(t.path)] == t.path {
+               if path[len(t.path)-1] == '/' {
+                       if t.sameP != nil {
+                               t.l.RUnlock()
+                               t.sameP.Store(path, f)
+                       } else {
+                               t.l.RUnlock()
+                               t.l.Lock()
+                               t.sameP = &WebPath{
+                                       path: path,
+                                       f:    f,
+                               }
+                               t.l.Unlock()
+                       }
+               } else {
+                       if t.next != nil {
+                               t.l.RUnlock()
+                               t.l.Lock()
+                               tmp := WebPath{path: t.path, f: t.f, sameP: t.sameP, next: t.next}
+                               t.path = path
+                               t.f = f
+                               t.next = &tmp
+                               t.l.Unlock()
+                       } else {
+                               t.l.RUnlock()
+                               t.l.Lock()
+                               t.next = &WebPath{
+                                       path: path,
+                                       f:    f,
+                               }
+                               t.l.Unlock()
+                       }
+               }
+       } else if len(path) < len(t.path) && t.path[:len(path)] == path {
+               t.l.RUnlock()
+               t.l.Lock()
+               tmp := WebPath{path: t.path, f: t.f, sameP: t.sameP, next: t.next}
+               t.path = path
+               t.f = f
+               t.sameP = &tmp
+               t.l.Unlock()
+       } else if t.next != nil {
+               t.l.RUnlock()
+               t.next.Store(path, f)
+       } else {
+               t.l.RUnlock()
+               t.l.Lock()
+               t.next = &WebPath{
+                       path: path,
+                       f:    f,
+               }
+               t.l.Unlock()
+       }
 }
 
-func NewSync(conf *http.Server) (o *Web) {
+func New(conf *http.Server) (o *Web) {
 
        o = new(Web)
 
-       o.mode = "sync"
        o.Server = conf
 
        if o.Server.Handler == nil {
@@ -48,23 +148,15 @@ func NewSync(conf *http.Server) (o *Web) {
 
        go o.Server.ListenAndServe()
 
-       o.mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
-               if wr, ok := o.wrs.Load(r.URL.Path); ok {
-                       if f, ok := wr.(func(http.ResponseWriter, *http.Request)); ok {
-                               f(w, r)
-                       }
-               }
-       })
-
        return
 }
 
-func NewSyncMap(conf *http.Server, m *sync.Map) (o *Web) {
+func NewSyncMap(conf *http.Server, m *WebPath) (o *WebSync) {
 
-       o = new(Web)
+       o = new(WebSync)
 
-       o.mode = "syncmap"
        o.Server = conf
+       o.wrs = m
 
        if o.Server.Handler == nil {
                o.mux = http.NewServeMux()
@@ -74,10 +166,8 @@ func NewSyncMap(conf *http.Server, m *sync.Map) (o *Web) {
        go o.Server.ListenAndServe()
 
        o.mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
-               if wr, ok := m.Load(r.URL.Path); ok {
-                       if f, ok := wr.(func(http.ResponseWriter, *http.Request)); ok {
-                               f(w, r)
-                       }
+               if f, ok := o.wrs.Load(r.URL.Path); ok {
+                       f(w, r)
                }
        })
 
@@ -85,21 +175,11 @@ func NewSyncMap(conf *http.Server, m *sync.Map) (o *Web) {
 }
 
 func (t *Web) Handle(path_func map[string]func(http.ResponseWriter, *http.Request)) {
-       if t.mode != "simple" {
-               panic("必须是New创建的")
-       }
        for k, v := range path_func {
                t.mux.HandleFunc(k, v)
        }
 }
 
-func (t *Web) HandleSync(path string, path_func func(http.ResponseWriter, *http.Request)) {
-       if t.mode != "sync" {
-               panic("必须是NewSync创建的")
-       }
-       t.wrs.Store(path, path_func)
-}
-
 func Easy_boot() *Web {
        s := New(&http.Server{
                Addr:         "127.0.0.1:" + strconv.Itoa(sys.Sys().GetFreePort()),
index 520c3d4b540503fb65b6b8b9c819928a1b3c2ef7..ec557c56d10d3b9215c6aac9bf59d81b919f2a7e 100644 (file)
@@ -1,9 +1,9 @@
 package part
 
 import (
+       "encoding/json"
        "net/http"
        "strconv"
-       "sync"
        "testing"
        "time"
 )
@@ -14,32 +14,80 @@ func Test_Server(t *testing.T) {
        time.Sleep(time.Second * time.Duration(100))
 }
 
-func Test_ServerSync(t *testing.T) {
-       s := NewSync(&http.Server{
-               Addr: "127.0.0.1:9090",
+func Test_ServerSyncMap(t *testing.T) {
+       var m WebPath
+       m.Store("/", func(w http.ResponseWriter, r *http.Request) {
+               w.Write([]byte("1"))
        })
+       NewSyncMap(&http.Server{
+               Addr: "127.0.0.1:9090",
+       }, &m)
        for i := 0; i < 20; i++ {
                time.Sleep(time.Second)
-               s.HandleSync("/1", func(w http.ResponseWriter, r *http.Request) {
-                       w.Write([]byte(strconv.Itoa(i)))
+               m.Store("/1", func(w http.ResponseWriter, r *http.Request) {
+
+                       type d struct {
+                               A string         `json:"a"`
+                               B []string       `json:"b"`
+                               C map[string]int `json:"c"`
+                       }
+
+                       t := strconv.Itoa(i)
+
+                       ResStruct{0, "ok", d{t, []string{t}, map[string]int{t: 1}}}.Write(w)
                })
        }
 }
 
-func Test_ServerSyncMap(t *testing.T) {
-       var m sync.Map
+func BenchmarkXxx(b *testing.B) {
+       var m WebPath
+       type d struct {
+               A string `json:"path"`
+       }
+       b.ResetTimer()
+       for i := 0; i < b.N; i++ {
+               m.Store("/", func(w http.ResponseWriter, r *http.Request) {
+                       ResStruct{0, "ok", d{"/"}}.Write(w)
+               })
+       }
+}
+
+func Test_ServerSyncMapP(t *testing.T) {
+       var m WebPath
+       type d struct {
+               A string `json:"path"`
+       }
        m.Store("/", func(w http.ResponseWriter, r *http.Request) {
-               w.Write([]byte("1"))
+               ResStruct{0, "ok", d{"/"}}.Write(w)
+       })
+       m.Store("/1", func(w http.ResponseWriter, r *http.Request) {
+               ResStruct{0, "ok", d{"/1"}}.Write(w)
        })
+       m.Store("/2", func(w http.ResponseWriter, r *http.Request) {
+               ResStruct{0, "ok", d{"/2"}}.Write(w)
+       })
+
        NewSyncMap(&http.Server{
                Addr: "127.0.0.1:9090",
        }, &m)
-       for i := 0; i < 20; i++ {
-               time.Sleep(time.Second)
-               m.Store("/1", func(w http.ResponseWriter, r *http.Request) {
-                       t.Log(r.URL.Path)
-                       t.Log(r.URL.EscapedPath())
-                       w.Write([]byte(strconv.Itoa(i)))
-               })
+
+       time.Sleep(time.Second * time.Duration(23))
+}
+
+type ResStruct struct {
+       Code    int    `json:"code"`
+       Message string `json:"message"`
+       Data    any    `json:"data"`
+}
+
+func (t ResStruct) Write(w http.ResponseWriter) {
+       w.Header().Set("Content-Type", "application/json")
+       data, e := json.Marshal(t)
+       if e != nil {
+               t.Code = -1
+               t.Data = nil
+               t.Message = e.Error()
+               data, _ = json.Marshal(t)
        }
+       w.Write(data)
 }