2024-02-13 12:04:56 +00:00
|
|
|
// Package httpp contains HTTP utilities.
|
|
|
|
package httpp
|
2023-05-16 18:12:45 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"crypto/tls"
|
2024-04-21 15:10:35 +00:00
|
|
|
"fmt"
|
2023-05-16 18:12:45 +00:00
|
|
|
"log"
|
|
|
|
"net"
|
|
|
|
"net/http"
|
|
|
|
"time"
|
|
|
|
|
2023-08-07 15:16:33 +00:00
|
|
|
"github.com/bluenviron/mediamtx/internal/logger"
|
2023-05-16 18:12:45 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type nilWriter struct{}
|
|
|
|
|
|
|
|
func (nilWriter) Write(p []byte) (int, error) {
|
|
|
|
return len(p), nil
|
|
|
|
}
|
|
|
|
|
2023-07-30 21:03:00 +00:00
|
|
|
// WrappedServer is a wrapper around http.Server that provides:
|
|
|
|
// - net.Listener allocation and closure
|
|
|
|
// - TLS allocation
|
|
|
|
// - exit on panic
|
2023-08-07 15:16:33 +00:00
|
|
|
// - logging
|
|
|
|
// - server header
|
|
|
|
// - filtering of invalid requests
|
2023-07-30 21:03:00 +00:00
|
|
|
type WrappedServer struct {
|
2024-04-21 15:10:35 +00:00
|
|
|
Network string
|
|
|
|
Address string
|
|
|
|
ReadTimeout time.Duration
|
|
|
|
Encryption bool
|
|
|
|
ServerCert string
|
|
|
|
ServerKey string
|
|
|
|
Handler http.Handler
|
|
|
|
Parent logger.Writer
|
|
|
|
|
2023-05-16 18:12:45 +00:00
|
|
|
ln net.Listener
|
|
|
|
inner *http.Server
|
|
|
|
}
|
|
|
|
|
2024-04-21 15:10:35 +00:00
|
|
|
// Initialize initializes a WrappedServer.
|
|
|
|
func (s *WrappedServer) Initialize() error {
|
2023-05-16 18:12:45 +00:00
|
|
|
var tlsConfig *tls.Config
|
2024-04-21 15:10:35 +00:00
|
|
|
if s.Encryption {
|
|
|
|
if s.ServerCert == "" {
|
|
|
|
return fmt.Errorf("server cert is missing")
|
|
|
|
}
|
|
|
|
crt, err := tls.LoadX509KeyPair(s.ServerCert, s.ServerKey)
|
2023-05-16 18:12:45 +00:00
|
|
|
if err != nil {
|
2024-04-21 15:10:35 +00:00
|
|
|
return err
|
2023-05-16 18:12:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
tlsConfig = &tls.Config{
|
|
|
|
Certificates: []tls.Certificate{crt},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-21 15:10:35 +00:00
|
|
|
var err error
|
|
|
|
s.ln, err = net.Listen(s.Network, s.Address)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
h := s.Handler
|
2023-08-07 15:16:33 +00:00
|
|
|
h = &handlerFilterRequests{h}
|
|
|
|
h = &handlerFilterRequests{h}
|
|
|
|
h = &handlerServerHeader{h}
|
2024-04-21 15:10:35 +00:00
|
|
|
h = &handlerLogger{h, s.Parent}
|
2023-08-07 15:16:33 +00:00
|
|
|
h = &handlerExitOnPanic{h}
|
|
|
|
|
2024-04-21 15:10:35 +00:00
|
|
|
s.inner = &http.Server{
|
|
|
|
Handler: h,
|
|
|
|
TLSConfig: tlsConfig,
|
|
|
|
ReadHeaderTimeout: s.ReadTimeout,
|
|
|
|
ErrorLog: log.New(&nilWriter{}, "", 0),
|
2023-05-16 18:12:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if tlsConfig != nil {
|
|
|
|
go s.inner.ServeTLS(s.ln, "", "")
|
|
|
|
} else {
|
|
|
|
go s.inner.Serve(s.ln)
|
|
|
|
}
|
|
|
|
|
2024-04-21 15:10:35 +00:00
|
|
|
return nil
|
2023-05-16 18:12:45 +00:00
|
|
|
}
|
|
|
|
|
2023-07-30 21:03:00 +00:00
|
|
|
// Close closes all resources and waits for all routines to return.
|
|
|
|
func (s *WrappedServer) Close() {
|
2024-01-15 16:54:52 +00:00
|
|
|
ctx, ctxCancel := context.WithCancel(context.Background())
|
|
|
|
ctxCancel()
|
|
|
|
s.inner.Shutdown(ctx)
|
2023-05-16 18:12:45 +00:00
|
|
|
s.ln.Close() // in case Shutdown() is called before Serve()
|
|
|
|
}
|