103 lines
2.0 KiB
Go
103 lines
2.0 KiB
Go
|
// server package contains core network layer components
|
||
|
package server
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"net"
|
||
|
"net/http"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
defaultReadTimeout = 10 * time.Second
|
||
|
defaultWriteTimeout = 10 * time.Second
|
||
|
defaultShutdownTimeout = 5 * time.Second
|
||
|
)
|
||
|
|
||
|
// Http Server object
|
||
|
type Server struct {
|
||
|
server *http.Server
|
||
|
notify chan error
|
||
|
shutdownTimeout time.Duration
|
||
|
}
|
||
|
|
||
|
func (s *Server) start() {
|
||
|
go func() {
|
||
|
s.notify <- s.server.ListenAndServe()
|
||
|
close(s.notify)
|
||
|
}()
|
||
|
}
|
||
|
|
||
|
// Notify return an error channel, that will contain error if server died
|
||
|
func (s *Server) Notify() <-chan error {
|
||
|
return s.notify
|
||
|
}
|
||
|
|
||
|
// Graceful shutdown
|
||
|
func (s *Server) Shutdown() error {
|
||
|
ctx, cancel := context.WithTimeout(context.Background(), s.shutdownTimeout)
|
||
|
defer cancel()
|
||
|
|
||
|
return s.server.Shutdown(ctx)
|
||
|
}
|
||
|
|
||
|
// New returns a new Server object
|
||
|
func New(
|
||
|
handler http.Handler,
|
||
|
addr string,
|
||
|
opts ...Option,
|
||
|
) *Server {
|
||
|
httpServer := &http.Server{
|
||
|
Handler: handler,
|
||
|
ReadTimeout: defaultReadTimeout,
|
||
|
WriteTimeout: defaultWriteTimeout,
|
||
|
Addr: addr,
|
||
|
}
|
||
|
|
||
|
s := &Server{
|
||
|
server: httpServer,
|
||
|
notify: make(chan error, 1),
|
||
|
shutdownTimeout: defaultShutdownTimeout,
|
||
|
}
|
||
|
|
||
|
// Apply options
|
||
|
for _, opt := range opts {
|
||
|
opt(s)
|
||
|
}
|
||
|
|
||
|
s.start()
|
||
|
|
||
|
return s
|
||
|
}
|
||
|
|
||
|
// Options configures Server
|
||
|
type Option func(s *Server)
|
||
|
|
||
|
// Port sets a specific port for Server to listen to
|
||
|
func Port(port string) Option {
|
||
|
return func(s *Server) {
|
||
|
s.server.Addr = net.JoinHostPort("", port)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// ReadTimeout sets a specific connection read timeout
|
||
|
func ReadTimeout(timeout time.Duration) Option {
|
||
|
return func(s *Server) {
|
||
|
s.server.ReadTimeout = timeout
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// WriteTimeout sets a specific connection write timeout
|
||
|
func WriteTimeout(timeout time.Duration) Option {
|
||
|
return func(s *Server) {
|
||
|
s.server.WriteTimeout = timeout
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// ShutdownTimeout sets a specific connection shutdown timeout
|
||
|
func ShutdownTimeout(timeout time.Duration) Option {
|
||
|
return func(s *Server) {
|
||
|
s.shutdownTimeout = timeout
|
||
|
}
|
||
|
}
|