feat: 新版 server 包 HTTP 基础实现

This commit is contained in:
kercylan98 2024-03-19 22:01:33 +08:00
parent e608e9257e
commit 37f35aa602
6 changed files with 207 additions and 4 deletions

10
go.mod
View File

@ -46,6 +46,7 @@ require (
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/panjf2000/gnet/v2 v2.3.6 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/samber/do/v2 v2.0.0-beta.5 // indirect
@ -60,16 +61,17 @@ require (
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
go.uber.org/multierr v1.7.0 // indirect
go.uber.org/zap v1.19.1 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/arch v0.3.0 // indirect
golang.org/x/exp v0.0.0-20221031165847-c99f073a8326 // indirect
golang.org/x/net v0.19.0 // indirect
golang.org/x/sys v0.16.0 // indirect
golang.org/x/sync v0.6.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/term v0.16.0 // indirect
golang.org/x/text v0.14.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

12
go.sum
View File

@ -113,6 +113,8 @@ github.com/panjf2000/ants/v2 v2.9.0 h1:SztCLkVxBRigbg+vt0S5QvF5vxAbxbKt09/YfAJ0t
github.com/panjf2000/ants/v2 v2.9.0/go.mod h1:7ZxyxsqE4vvW0M7LSD8aI3cKwgFhBHbxnlN8mDqHa1I=
github.com/panjf2000/gnet v1.6.7 h1:zv1k6kw80sG5ZQrLpbbFDheNCm50zm3z2e3ck5GwMOM=
github.com/panjf2000/gnet v1.6.7/go.mod h1:KcOU7QsCaCBjeD5kyshBIamG3d9kAQtlob4Y0v0E+sc=
github.com/panjf2000/gnet/v2 v2.3.6 h1:BUHjMPJaNO8N5rQZmhKce9/Iu2ryeMjhKPEOi+ecisQ=
github.com/panjf2000/gnet/v2 v2.3.6/go.mod h1:R+X5M5YBpOGMVP/92OJ02P35SbmoHjiL7GnaBhht6GE=
github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
@ -192,8 +194,12 @@ go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpK
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec=
go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI=
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
@ -241,6 +247,8 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -260,6 +268,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
@ -324,6 +334,8 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@ -0,0 +1,69 @@
package server
import (
"fmt"
"github.com/panjf2000/ants/v2"
"github.com/panjf2000/gnet/v2"
"time"
)
func newEventHandler(trafficker Trafficker) (handler *eventHandler, err error) {
var wp *ants.Pool
if wp, err = ants.NewPool(ants.DefaultAntsPoolSize, ants.WithNonblocking(true)); err != nil {
return
}
handler = &eventHandler{
trafficker: trafficker,
workerPool: wp,
}
return
}
type (
Trafficker interface {
OnBoot() error
OnTraffic(c gnet.Conn, packet []byte)
}
eventHandler struct {
trafficker Trafficker
workerPool *ants.Pool
}
)
func (e *eventHandler) OnBoot(eng gnet.Engine) (action gnet.Action) {
if err := e.trafficker.OnBoot(); err != nil {
action = gnet.Shutdown
}
return
}
func (e *eventHandler) OnShutdown(eng gnet.Engine) {
return
}
func (e *eventHandler) OnOpen(c gnet.Conn) (out []byte, action gnet.Action) {
return
}
func (e *eventHandler) OnClose(c gnet.Conn, err error) (action gnet.Action) {
fmt.Println("断开")
return
}
func (e *eventHandler) OnTraffic(c gnet.Conn) (action gnet.Action) {
buf, err := c.Next(-1)
if err != nil {
return
}
var packet = make([]byte, len(buf))
copy(packet, buf)
err = e.workerPool.Submit(func() {
e.trafficker.OnTraffic(c, packet)
})
return
}
func (e *eventHandler) OnTick() (delay time.Duration, action gnet.Action) {
return
}

20
server/v2/server.go Normal file
View File

@ -0,0 +1,20 @@
package server
import "github.com/panjf2000/gnet/v2"
func NewServer(trafficker Trafficker) *Server {
srv := &Server{
trafficker: trafficker,
}
return srv
}
type Server struct {
trafficker Trafficker
}
func (s *Server) Run(protoAddr string) (err error) {
var handler *eventHandler
handler, err = newEventHandler(s.trafficker)
return gnet.Run(handler, protoAddr)
}

View File

@ -0,0 +1,42 @@
package traffickers
import (
"bufio"
"bytes"
"github.com/kercylan98/minotaur/server/v2"
"github.com/kercylan98/minotaur/utils/hub"
"github.com/panjf2000/gnet/v2"
netHttp "net/http"
)
func Http(handler netHttp.Handler) server.Trafficker {
return &http{
handler: handler,
}
}
type http struct {
handler netHttp.Handler
rwp *hub.ObjectPool[*httpResponseWriter]
}
func (h *http) OnBoot() error {
h.rwp = hub.NewObjectPool[httpResponseWriter](func() *httpResponseWriter {
return new(httpResponseWriter)
}, func(data *httpResponseWriter) {
data.reset()
})
return nil
}
func (h *http) OnTraffic(c gnet.Conn, packet []byte) {
httpRequest, err := netHttp.ReadRequest(bufio.NewReader(bytes.NewReader(packet)))
if err != nil {
return
}
responseWriter := h.rwp.Get()
responseWriter.init(c)
h.handler.ServeHTTP(responseWriter, httpRequest)
}

View File

@ -0,0 +1,58 @@
package traffickers
import (
"bytes"
"github.com/panjf2000/gnet/v2"
netHttp "net/http"
"strconv"
"sync"
)
type httpResponseWriter struct {
c gnet.Conn
statusCode int
header netHttp.Header
}
func (w *httpResponseWriter) init(c gnet.Conn) {
w.c = c
w.statusCode = 200
w.header = make(netHttp.Header)
}
func (w *httpResponseWriter) reset() {
w.c = nil
w.statusCode = 200
w.header = nil
}
func (w *httpResponseWriter) Header() netHttp.Header {
return w.header
}
func (w *httpResponseWriter) Write(b []byte) (n int, err error) {
var buf bytes.Buffer
buf.WriteString("HTTP/1.1 ")
buf.WriteString(netHttp.StatusText(w.statusCode))
buf.WriteString("\r\n")
w.header.Set("Content-Length", strconv.Itoa(len(b)))
if err = w.header.Write(&buf); err != nil {
return
}
buf.WriteString("\r\n")
buf.Write(b)
res := buf.Bytes()
var wg sync.WaitGroup
wg.Add(1)
err = w.c.AsyncWrite(res, func(c gnet.Conn, e error) error {
err = e
wg.Done()
return nil
})
wg.Wait()
return len(res), err
}
func (w *httpResponseWriter) WriteHeader(statusCode int) {
w.statusCode = statusCode
}