feat: 新版 server 包 HTTP 基础实现
This commit is contained in:
parent
e608e9257e
commit
37f35aa602
10
go.mod
10
go.mod
|
@ -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
12
go.sum
|
@ -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=
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue