1
0
mirror of https://github.com/labstack/echo.git synced 2025-04-25 12:24:55 +02:00

Issue 655 (#657)

* Closes #655, closes #649

Signed-off-by: Vishal Rana <vr@labstack.com>

* Added http/1.1 to the list
This commit is contained in:
Vishal Rana 2016-09-12 06:18:58 -07:00 committed by GitHub
parent 03efe4d61b
commit 322b375a37
5 changed files with 69 additions and 15 deletions

13
echo.go
View File

@ -58,6 +58,7 @@ import (
type ( type (
// Echo is the top-level framework instance. // Echo is the top-level framework instance.
Echo struct { Echo struct {
server engine.Server
premiddleware []MiddlewareFunc premiddleware []MiddlewareFunc
middleware []MiddlewareFunc middleware []MiddlewareFunc
maxParam *int maxParam *int
@ -569,16 +570,20 @@ func (e *Echo) ServeHTTP(req engine.Request, res engine.Response) {
} }
// Run starts the HTTP server. // Run starts the HTTP server.
func (e *Echo) Run(s engine.Server) { func (e *Echo) Run(s engine.Server) error {
e.server = s
s.SetHandler(e) s.SetHandler(e)
s.SetLogger(e.logger) s.SetLogger(e.logger)
if e.Debug() { if e.Debug() {
e.SetLogLevel(glog.DEBUG) e.SetLogLevel(glog.DEBUG)
e.logger.Debug("running in debug mode") e.logger.Debug("running in debug mode")
} }
if err := s.Start(); err != nil { return s.Start()
panic(fmt.Sprintf("echo: %v", err)) }
}
// Stop stops the HTTP server.
func (e *Echo) Stop() error {
return e.server.Stop()
} }
// NewHTTPError creates a new HTTPError instance. // NewHTTPError creates a new HTTPError instance.

View File

@ -21,6 +21,9 @@ type (
// Start starts the HTTP server. // Start starts the HTTP server.
Start() error Start() error
// Stop stops the HTTP server by closing underlying TCP connection.
Stop() error
} }
// Request defines the interface for HTTP request. // Request defines the interface for HTTP request.
@ -205,6 +208,7 @@ type (
Listener net.Listener // Custom `net.Listener`. If set, server accepts connections on it. Listener net.Listener // Custom `net.Listener`. If set, server accepts connections on it.
TLSCertFile string // TLS certificate file path. TLSCertFile string // TLS certificate file path.
TLSKeyFile string // TLS key file path. TLSKeyFile string // TLS key file path.
DisableHTTP2 bool // Disables HTTP/2.
ReadTimeout time.Duration // Maximum duration before timing out read of the request. ReadTimeout time.Duration // Maximum duration before timing out read of the request.
WriteTimeout time.Duration // Maximum duration before timing out write of the response. WriteTimeout time.Duration // Maximum duration before timing out write of the response.
} }

View File

@ -109,6 +109,12 @@ func (s *Server) Start() error {
} }
// Stop implements `engine.Server#Stop` function.
func (s *Server) Stop() error {
// TODO: implement `engine.Server#Stop` function
return nil
}
func (s *Server) startDefaultListener() error { func (s *Server) startDefaultListener() error {
c := s.config c := s.config
if c.TLSCertFile != "" && c.TLSKeyFile != "" { if c.TLSCertFile != "" && c.TLSKeyFile != "" {

View File

@ -1,8 +1,11 @@
package standard package standard
import ( import (
"crypto/tls"
"net"
"net/http" "net/http"
"sync" "sync"
"time"
"github.com/labstack/echo" "github.com/labstack/echo"
"github.com/labstack/echo/engine" "github.com/labstack/echo/engine"
@ -102,23 +105,37 @@ func (s *Server) SetLogger(l log.Logger) {
// Start implements `engine.Server#Start` function. // Start implements `engine.Server#Start` function.
func (s *Server) Start() error { func (s *Server) Start() error {
if s.config.Listener == nil { if s.config.Listener == nil {
return s.startDefaultListener() ln, err := net.Listen("tcp", s.config.Address)
if err != nil {
return err
} }
return s.startCustomListener()
}
func (s *Server) startDefaultListener() error { if s.config.TLSCertFile != "" && s.config.TLSKeyFile != "" {
c := s.config config := &tls.Config{
if c.TLSCertFile != "" && c.TLSKeyFile != "" { NextProtos: []string{"http/1.1"},
return s.ListenAndServeTLS(c.TLSCertFile, c.TLSKeyFile) }
if !s.config.DisableHTTP2 {
config.NextProtos = append(config.NextProtos, "h2")
}
config.Certificates = make([]tls.Certificate, 1)
config.Certificates[0], err = tls.LoadX509KeyPair(s.config.TLSCertFile, s.config.TLSKeyFile)
if err != nil {
return err
}
s.config.Listener = tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, config)
} else {
s.config.Listener = tcpKeepAliveListener{ln.(*net.TCPListener)}
}
} }
return s.ListenAndServe()
}
func (s *Server) startCustomListener() error {
return s.Serve(s.config.Listener) return s.Serve(s.config.Listener)
} }
// Stop implements `engine.Server#Stop` function.
func (s *Server) Stop() error {
return s.config.Listener.Close()
}
// ServeHTTP implements `http.Handler` interface. // ServeHTTP implements `http.Handler` interface.
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Request // Request
@ -170,3 +187,21 @@ func WrapMiddleware(m func(http.Handler) http.Handler) echo.MiddlewareFunc {
} }
} }
} }
// tcpKeepAliveListener sets TCP keep-alive timeouts on accepted
// connections. It's used by ListenAndServe and ListenAndServeTLS so
// dead TCP connections (e.g. closing laptop mid-download) eventually
// go away.
type tcpKeepAliveListener struct {
*net.TCPListener
}
func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
tc, err := ln.AcceptTCP()
if err != nil {
return
}
tc.SetKeepAlive(true)
tc.SetKeepAlivePeriod(3 * time.Minute)
return tc, nil
}

View File

@ -88,6 +88,10 @@ func (s *Server) Start() error {
return s.startCustomListener() return s.startCustomListener()
} }
func (s *Server) Stop() error {
return nil
}
func (s *Server) startDefaultListener() error { func (s *Server) startDefaultListener() error {
c := s.config c := s.config
if c.TLSCertFile != "" && c.TLSKeyFile != "" { if c.TLSCertFile != "" && c.TLSKeyFile != "" {