caddy/modules/caddyhttp/caddyhttp.go
Matthew Holt 27ff6aeccb Fix goroutine leak in Run
D'oh, the servers' Shutdown() would never be called because they were
never added to the list of servers.

Thanks Danny for finding this.
2019-03-27 12:36:30 -06:00

109 lines
2.2 KiB
Go

package caddyhttp
import (
"context"
"fmt"
"log"
"net"
"net/http"
"strconv"
"strings"
"time"
"bitbucket.org/lightcodelabs/caddy2"
)
func init() {
err := caddy2.RegisterModule(caddy2.Module{
Name: "http",
New: func() (interface{}, error) { return new(httpModuleConfig), nil },
})
if err != nil {
log.Fatal(err)
}
}
type httpModuleConfig struct {
Servers map[string]httpServerConfig `json:"servers"`
servers []*http.Server
}
func (hc *httpModuleConfig) Run() error {
// fmt.Printf("RUNNING: %#v\n", hc)
for _, srv := range hc.Servers {
s := &http.Server{
ReadTimeout: time.Duration(srv.ReadTimeout),
ReadHeaderTimeout: time.Duration(srv.ReadHeaderTimeout),
}
for _, lnAddr := range srv.Listen {
proto, addrs, err := parseListenAddr(lnAddr)
if err != nil {
return fmt.Errorf("parsing listen address '%s': %v", lnAddr, err)
}
for _, addr := range addrs {
ln, err := caddy2.Listen(proto, addr)
if err != nil {
return fmt.Errorf("%s: listening on %s: %v", proto, addr, err)
}
go s.Serve(ln)
hc.servers = append(hc.servers, s)
}
}
}
return nil
}
func (hc *httpModuleConfig) Cancel() error {
for _, s := range hc.servers {
err := s.Shutdown(context.Background()) // TODO
if err != nil {
return err
}
}
return nil
}
func parseListenAddr(a string) (proto string, addrs []string, err error) {
proto = "tcp"
if idx := strings.Index(a, "/"); idx >= 0 {
proto = strings.ToLower(strings.TrimSpace(a[:idx]))
a = a[idx+1:]
}
var host, port string
host, port, err = net.SplitHostPort(a)
if err != nil {
return
}
ports := strings.SplitN(port, "-", 2)
if len(ports) == 1 {
ports = append(ports, ports[0])
}
var start, end int
start, err = strconv.Atoi(ports[0])
if err != nil {
return
}
end, err = strconv.Atoi(ports[1])
if err != nil {
return
}
if end < start {
err = fmt.Errorf("end port must be greater than start port")
return
}
for p := start; p <= end; p++ {
addrs = append(addrs, net.JoinHostPort(host, fmt.Sprintf("%d", p)))
}
return
}
type httpServerConfig struct {
Listen []string `json:"listen"`
ReadTimeout caddy2.Duration `json:"read_timeout"`
ReadHeaderTimeout caddy2.Duration `json:"read_header_timeout"`
}