func (s *Server) Stop() error {
	ctx, cancel := context.WithTimeout(context.Background(), s.connTimeout)
	defer cancel()
	err := s.Server.Shutdown(ctx)
	if err != nil {
		return err
	}
	if s.tlsGovChan != nil {
		close(s.tlsGovChan)
	}
	return nil
}
Stop stops s gracefully (or forcefully after timeout) and
closes its listener.
package httpserver
import (
	"context"
	"crypto/tls"
	"errors"
	"fmt"
	"log"
	"net"
	"net/http"
	"net/url"
	"os"
	"path"
	"path/filepath"
	"runtime"
	"strings"
	"time"
	"github.com/lucas-clemente/quic-go/http3"
	"github.com/tmpim/casket"
	"github.com/tmpim/casket/caskethttp/staticfiles"
	"github.com/tmpim/casket/caskettls"
	"github.com/tmpim/casket/telemetry"
)
type Server struct {
	Server      *http.Server
	quicServer  *http3.Server
	sites       []*SiteConfig
	connTimeout time.Duration  
	tlsGovChan  chan struct{}  
	vhosts      *vhostTrie
}
var _ casket.GracefulServer = new(Server)
var defaultALPN = []string{"h2", "http/1.1"}
func makeTLSConfig(group []*SiteConfig) (*tls.Config, error) {
	var tlsConfigs []*caskettls.Config
	for i := range group {
		if HTTP2 && len(group[i].TLS.ALPN) == 0 {
			group[i].TLS.ALPN = defaultALPN
		}
		tlsConfigs = append(tlsConfigs, group[i].TLS)
	}
	return caskettls.MakeTLSConfig(tlsConfigs)
}
func getFallbacks(sites []*SiteConfig) []string {
	fallbacks := []string{}
	for _, sc := range sites {
		if sc.FallbackSite {
			fallbacks = append(fallbacks, sc.Addr.Host)
		}
	}
	return fallbacks
}
func NewServer(addr string, group []*SiteConfig) (*Server, error) {
	s := &Server{
		Server:      makeHTTPServerWithTimeouts(addr, group),
		vhosts:      newVHostTrie(),
		sites:       group,
		connTimeout: GracefulTimeout,
	}
	s.vhosts.fallbackHosts = append(s.vhosts.fallbackHosts, getFallbacks(group)...)
	s.Server = makeHTTPServerWithHeaderLimit(s.Server, group)
	s.Server.Handler = s  
	tlsConfig, err := makeTLSConfig(group)
	if err != nil {
		return nil, err
	}
	s.Server.TLSConfig = tlsConfig
	if s.Server.TLSConfig != nil {
		if HTTP2 && QUIC {
			s.quicServer = &http3.Server{Server: s.Server}
			s.Server.Handler = s.wrapWithSvcHeaders(s.Server.Handler)
		}
		tlsh := &tlsHandler{next: s.Server.Handler}
		s.Server.Handler = tlsh  
		s.Server.ConnState = func(c net.Conn, cs http.ConnState) {
			if tlsh.listener != nil {
				if cs == http.StateHijacked || cs == http.StateClosed {
					tlsh.listener.helloInfosMu.Lock()
					delete(tlsh.listener.helloInfos, c.RemoteAddr().String())
					tlsh.listener.helloInfosMu.Unlock()
				}
			}
		}
		if HTTP2 && len(s.Server.TLSConfig.NextProtos) == 0 {
			s.Server.TLSConfig.NextProtos = defaultALPN
		}
	}
	for _, site := range group {
		stack := Handler(staticfiles.FileServer{Root: http.Dir(site.Root), Hide: site.HiddenFiles, IndexPages: site.IndexPages})
		for i := len(site.middleware) - 1; i >= 0; i-- {
			stack = site.middleware[i](stack)
		}
		site.middlewareChain = stack
		s.vhosts.Insert(site.Addr.VHost(), site)
	}
	return s, nil
}
func makeHTTPServerWithHeaderLimit(s *http.Server, group []*SiteConfig) *http.Server {
	var min int64
	for _, cfg := range group {
		limit := cfg.Limits.MaxRequestHeaderSize
		if limit == 0 {
			continue
		}
		if min == 0 {
			min = limit
		}
		if limit < min {
			min = limit
		}
	}
	if min > 0 {
		s.MaxHeaderBytes = int(min)
	}
	return s
}
func makeHTTPServerWithTimeouts(addr string, group []*SiteConfig) *http.Server {
	var min Timeouts
	for _, cfg := range group {
		if cfg.Timeouts.ReadTimeoutSet &&
			(!min.ReadTimeoutSet || cfg.Timeouts.ReadTimeout < min.ReadTimeout) {
			min.ReadTimeoutSet = true
			min.ReadTimeout = cfg.Timeouts.ReadTimeout
		}
		if cfg.Timeouts.ReadHeaderTimeoutSet &&
			(!min.ReadHeaderTimeoutSet || cfg.Timeouts.ReadHeaderTimeout < min.ReadHeaderTimeout) {
			min.ReadHeaderTimeoutSet = true
			min.ReadHeaderTimeout = cfg.Timeouts.ReadHeaderTimeout
		}
		if cfg.Timeouts.WriteTimeoutSet &&
			(!min.WriteTimeoutSet || cfg.Timeouts.WriteTimeout < min.WriteTimeout) {
			min.WriteTimeoutSet = true
			min.WriteTimeout = cfg.Timeouts.WriteTimeout
		}
		if cfg.Timeouts.IdleTimeoutSet &&
			(!min.IdleTimeoutSet || cfg.Timeouts.IdleTimeout < min.IdleTimeout) {
			min.IdleTimeoutSet = true
			min.IdleTimeout = cfg.Timeouts.IdleTimeout
		}
	}
	if !min.ReadTimeoutSet {
		min.ReadTimeout = defaultTimeouts.ReadTimeout
	}
	if !min.ReadHeaderTimeoutSet {
		min.ReadHeaderTimeout = defaultTimeouts.ReadHeaderTimeout
	}
	if !min.WriteTimeoutSet {
		min.WriteTimeout = defaultTimeouts.WriteTimeout
	}
	if !min.IdleTimeoutSet {
		min.IdleTimeout = defaultTimeouts.IdleTimeout
	}
	return &http.Server{
		Addr:              addr,
		ReadTimeout:       min.ReadTimeout,
		ReadHeaderTimeout: min.ReadHeaderTimeout,
		WriteTimeout:      min.WriteTimeout,
		IdleTimeout:       min.IdleTimeout,
	}
}
func (s *Server) wrapWithSvcHeaders(previousHandler http.Handler) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		if err := s.quicServer.SetQuicHeaders(w.Header()); err != nil {
			log.Println("[Error] failed to set proper headers for QUIC: ", err)
		}
		previousHandler.ServeHTTP(w, r)
	}
}
func (s *Server) Listen() (net.Listener, error) {
	if s.Server == nil {
		return nil, fmt.Errorf("server field is nil")
	}
	ln, err := net.Listen("tcp", s.Server.Addr)
	if err != nil {
		var succeeded bool
		if runtime.GOOS == "windows" {
			for i := 0; i < 20; i++ {
				time.Sleep(100 * time.Millisecond)
				ln, err = net.Listen("tcp", s.Server.Addr)
				if err == nil {
					succeeded = true
					break
				}
			}
		}
		if !succeeded {
			return nil, err
		}
	}
	if tcpLn, ok := ln.(*net.TCPListener); ok {
		ln = tcpKeepAliveListener{TCPListener: tcpLn}
	}
	cln := s.WrapListener(ln)
	return cln.(casket.Listener), nil
}
func (s *Server) WrapListener(ln net.Listener) net.Listener {
	if ln == nil {
		return nil
	}
	cln := ln.(casket.Listener)
	for _, site := range s.sites {
		for _, m := range site.listenerMiddleware {
			cln = m(cln)
		}
	}
	return cln
}
func (s *Server) ListenPacket() (net.PacketConn, error) {
	if QUIC {
		udpAddr, err := net.ResolveUDPAddr("udp", s.Server.Addr)
		if err != nil {
			return nil, err
		}
		return net.ListenUDP("udp", udpAddr)
	}
	return nil, nil
}
func (s *Server) Serve(ln net.Listener) error {
	if s.Server.TLSConfig != nil {
		ln = newTLSListener(ln, s.Server.TLSConfig)
		if handler, ok := s.Server.Handler.(*tlsHandler); ok {
			handler.listener = ln.(*tlsHelloListener)
		}
		s.tlsGovChan = caskettls.RotateSessionTicketKeys(s.Server.TLSConfig)
	}
	defer func() {
		if s.quicServer != nil {
			if err := s.quicServer.Close(); err != nil {
				log.Println("[ERROR] failed to close QUIC server: ", err)
			}
		}
	}()
	err := s.Server.Serve(ln)
	if err != nil && err != http.ErrServerClosed {
		return err
	}
	return nil
}
func (s *Server) ServePacket(pc net.PacketConn) error {
	if s.quicServer != nil {
		err := s.quicServer.Serve(pc.(*net.UDPConn))
		return fmt.Errorf("serving QUIC connections: %v", err)
	}
	return nil
}
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	defer func() {
		if rec := recover(); rec != nil {
			log.Printf("[PANIC] %v", rec)
			DefaultErrorFunc(w, r, http.StatusInternalServerError)
		}
	}()
	ua := r.Header.Get("User-Agent")
	if len(ua) > 512 {
		ua = ua[:512]
	}
	uaHash := telemetry.FastHash([]byte(ua))  
	go telemetry.SetNested("http_user_agent", uaHash, ua)
	go telemetry.AppendUnique("http_user_agent_count", uaHash)
	go telemetry.Increment("http_request_count")
	urlCopy := *r.URL
	if r.URL.User != nil {
		userInfo := new(url.Userinfo)
		*userInfo = *r.URL.User
		urlCopy.User = userInfo
	}
	c := context.WithValue(r.Context(), OriginalURLCtxKey, urlCopy)
	r = r.WithContext(c)
	replacer := NewReplacer(r, nil, "")
	c = context.WithValue(r.Context(), ReplacerCtxKey, replacer)
	r = r.WithContext(c)
	w.Header().Set("Server", casket.AppName)
	status, _ := s.serveHTTP(w, r)
	if status >= 400 {
		DefaultErrorFunc(w, r, status)
	}
}
func (s *Server) serveHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
	hostname, _, err := net.SplitHostPort(r.Host)
	if err != nil {
		hostname = r.Host
	}
	vhost, pathPrefix := s.vhosts.Match(hostname + r.URL.Path)
	c := context.WithValue(r.Context(), casket.CtxKey("path_prefix"), pathPrefix)
	r = r.WithContext(c)
	if vhost == nil {
		if len(s.sites) > 0 && s.sites[0].TLS.Manager.HandleHTTPChallenge(w, r) {
			return 0, nil
		}
		remoteHost, _, err := net.SplitHostPort(r.RemoteAddr)
		if err != nil {
			remoteHost = r.RemoteAddr
		}
		WriteSiteNotFound(w, r)  
		log.Printf("[INFO] %s - No such site at %s (Remote: %s, Referer: %s)",
			hostname, s.Server.Addr, remoteHost, r.Header.Get("Referer"))
		return 0, nil
	}
	if vhost.TLS.Manager.HandleHTTPChallenge(w, r) {
		return 0, nil
	}
	if pathPrefix != "/" {
		r.URL = trimPathPrefix(r.URL, pathPrefix)
	}
	if !vhost.TLS.InsecureDisableSNIMatching && r.TLS != nil &&
		vhost.TLS.ClientAuth != tls.NoClientCert &&
		strings.ToLower(r.TLS.ServerName) != strings.ToLower(hostname) {
		r.Close = true
		log.Printf("[ERROR] %s - strict host matching: SNI (%s) and HTTP Host (%s) values differ",
			vhost.Addr, r.TLS.ServerName, hostname)
		return http.StatusForbidden, nil
	}
	return vhost.middlewareChain.ServeHTTP(w, r)
}
func trimPathPrefix(u *url.URL, prefix string) *url.URL {
	trimmedPath := strings.TrimPrefix(u.EscapedPath(), prefix)
	if !strings.HasPrefix(trimmedPath, "/") {
		trimmedPath = "/" + trimmedPath
	}
	trimmedURI := trimmedPath
	if u.RawQuery != "" || u.ForceQuery == true {
		trimmedURI = trimmedPath + "?" + u.RawQuery
	}
	if u.Fragment != "" {
		trimmedURI = trimmedURI + "#" + u.Fragment
	}
	trimmedURL, err := url.Parse(trimmedURI)
	if err != nil {
		log.Printf("[ERROR] Unable to parse trimmed URL %s: %v", trimmedURI, err)
		return u
	}
	return trimmedURL
}
func (s *Server) Address() string {
	return s.Server.Addr
}