Skip to content

Commit 4727bc6

Browse files
committed
Adding Echo#ListenerNetwork as configuration
Now Echo could be configured to Listen on tcp supported networks of net.Listen Go standard library (tcp, tcp4, tcp6)
1 parent 095af21 commit 4727bc6

File tree

2 files changed

+78
-8
lines changed

2 files changed

+78
-8
lines changed

echo.go

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ type (
9292
Renderer Renderer
9393
Logger Logger
9494
IPExtractor IPExtractor
95+
ListenerNetwork string
9596
}
9697

9798
// Route contains a handler and information for matching against requests.
@@ -281,6 +282,7 @@ var (
281282
ErrInvalidRedirectCode = errors.New("invalid redirect status code")
282283
ErrCookieNotFound = errors.New("cookie not found")
283284
ErrInvalidCertOrKeyType = errors.New("invalid cert or key type, must be string or []byte")
285+
ErrInvalidListenerNetwork = errors.New("invalid listener network")
284286
)
285287

286288
// Error handlers
@@ -302,9 +304,10 @@ func New() (e *Echo) {
302304
AutoTLSManager: autocert.Manager{
303305
Prompt: autocert.AcceptTOS,
304306
},
305-
Logger: log.New("echo"),
306-
colorer: color.New(),
307-
maxParam: new(int),
307+
Logger: log.New("echo"),
308+
colorer: color.New(),
309+
maxParam: new(int),
310+
ListenerNetwork: "tcp",
308311
}
309312
e.Server.Handler = e
310313
e.TLSServer.Handler = e
@@ -712,7 +715,7 @@ func (e *Echo) StartServer(s *http.Server) (err error) {
712715

713716
if s.TLSConfig == nil {
714717
if e.Listener == nil {
715-
e.Listener, err = newListener(s.Addr)
718+
e.Listener, err = newListener(s.Addr, e.ListenerNetwork)
716719
if err != nil {
717720
return err
718721
}
@@ -723,7 +726,7 @@ func (e *Echo) StartServer(s *http.Server) (err error) {
723726
return s.Serve(e.Listener)
724727
}
725728
if e.TLSListener == nil {
726-
l, err := newListener(s.Addr)
729+
l, err := newListener(s.Addr, e.ListenerNetwork)
727730
if err != nil {
728731
return err
729732
}
@@ -752,7 +755,7 @@ func (e *Echo) StartH2CServer(address string, h2s *http2.Server) (err error) {
752755
}
753756

754757
if e.Listener == nil {
755-
e.Listener, err = newListener(s.Addr)
758+
e.Listener, err = newListener(s.Addr, e.ListenerNetwork)
756759
if err != nil {
757760
return err
758761
}
@@ -873,8 +876,11 @@ func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
873876
return
874877
}
875878

876-
func newListener(address string) (*tcpKeepAliveListener, error) {
877-
l, err := net.Listen("tcp", address)
879+
func newListener(address, network string) (*tcpKeepAliveListener, error) {
880+
if network != "tcp" && network != "tcp4" && network != "tcp6" {
881+
return nil, ErrInvalidListenerNetwork
882+
}
883+
l, err := net.Listen(network, address)
878884
if err != nil {
879885
return nil, err
880886
}

echo_test.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"bytes"
55
stdContext "context"
66
"errors"
7+
"fmt"
78
"io/ioutil"
89
"net/http"
910
"net/http/httptest"
@@ -609,3 +610,66 @@ func TestEchoShutdown(t *testing.T) {
609610
err := <-errCh
610611
assert.Equal(t, err.Error(), "http: Server closed")
611612
}
613+
614+
var listenerNetworkTests = []struct {
615+
test string
616+
network string
617+
address string
618+
}{
619+
{"tcp ipv4 address", "tcp", "127.0.0.1:1323"},
620+
{"tcp ipv6 address", "tcp", "[::1]:1323"},
621+
{"tcp4 ipv4 address", "tcp4", "127.0.0.1:1323"},
622+
{"tcp6 ipv6 address", "tcp6", "[::1]:1323"},
623+
}
624+
625+
func TestEchoListenerNetwork(t *testing.T) {
626+
for _, tt := range listenerNetworkTests {
627+
t.Run(tt.test, func(t *testing.T) {
628+
e := New()
629+
e.ListenerNetwork = tt.network
630+
631+
// HandlerFunc
632+
e.GET("/ok", func(c Context) error {
633+
return c.String(http.StatusOK, "OK")
634+
})
635+
636+
errCh := make(chan error)
637+
638+
go func() {
639+
errCh <- e.Start(tt.address)
640+
}()
641+
642+
time.Sleep(200 * time.Millisecond)
643+
644+
if resp, err := http.Get(fmt.Sprintf("http://%s/ok", tt.address)); err == nil {
645+
defer resp.Body.Close()
646+
assert.Equal(t, http.StatusOK, resp.StatusCode)
647+
648+
if body, err := ioutil.ReadAll(resp.Body); err == nil {
649+
assert.Equal(t, "OK", string(body))
650+
} else {
651+
assert.Fail(t, err.Error())
652+
}
653+
654+
} else {
655+
assert.Fail(t, err.Error())
656+
}
657+
658+
if err := e.Close(); err != nil {
659+
t.Fatal(err)
660+
}
661+
})
662+
}
663+
}
664+
665+
func TestEchoListenerNetworkInvalid(t *testing.T) {
666+
e := New()
667+
e.ListenerNetwork = "unix"
668+
669+
// HandlerFunc
670+
e.GET("/ok", func(c Context) error {
671+
return c.String(http.StatusOK, "OK")
672+
})
673+
674+
assert.Equal(t, ErrInvalidListenerNetwork, e.Start(":1323"))
675+
}

0 commit comments

Comments
 (0)