termtap/internal/proxy/server.go
Hayden Hargreaves 365fb43eca feat: FINALLY got HTTPS working :)
Going to work on UI now.
2026-04-18 22:25:04 -07:00

110 lines
2.2 KiB
Go

package proxy
import (
"context"
"fmt"
"net"
"net/http"
"time"
"termtap.dev/internal/model"
)
const (
proxyReadHeaderTimeout = 10 * time.Second
proxyIdleTimeout = 30 * time.Second
)
func NewProxyServer(addr string, ch chan<- model.Event) (*model.ProxyServer, error) {
ca, err := loadOrCreateCertificateAuthority()
if err != nil {
return nil, err
}
trusted, err := ca.IsTrustedBySystem()
if err != nil {
trusted = false
}
listener, err := net.Listen("tcp", addr)
if err != nil {
return nil, err
}
url := fmt.Sprintf("http://%s", listener.Addr().String())
ps := &model.ProxyServer{
Listener: &listener,
Url: url,
CACertPath: ca.CertPath(),
CAReady: true,
CACreated: ca.WasCreated(),
CATrusted: trusted,
Conns: make(map[net.Conn]struct{}),
}
ps.Server = &http.Server{
Handler: proxyHandler(ch, ca, ps),
ReadHeaderTimeout: proxyReadHeaderTimeout,
IdleTimeout: proxyIdleTimeout,
}
return ps, nil
}
// BUG: Not sure what all this does
func Destroy(ps *model.ProxyServer, ch chan<- model.Event) {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
if ps != nil && ps.Server != nil {
closeTrackedConnections(ps)
_ = ps.Server.Shutdown(ctx)
ch <- model.Event{
Time: time.Now().Local(),
Type: model.EventTypeProxyStopped,
Body: "proxy server was destroyed",
}
}
}
func trackConnection(ps *model.ProxyServer, conn net.Conn) {
if ps == nil || conn == nil {
return
}
ps.ConnMu.Lock()
defer ps.ConnMu.Unlock()
ps.Conns[conn] = struct{}{}
}
func untrackConnection(ps *model.ProxyServer, conn net.Conn) {
if ps == nil || conn == nil {
return
}
ps.ConnMu.Lock()
defer ps.ConnMu.Unlock()
delete(ps.Conns, conn)
}
func closeTrackedConnections(ps *model.ProxyServer) {
if ps == nil {
return
}
// Get all of the connections while claiming the mutex.
// Then close the mutex to allow access to the server object quicker.
// Then a loop can run to close the connections, without needing access
// to the server's mutex.
ps.ConnMu.Lock()
conns := make([]net.Conn, 0, len(ps.Conns))
for conn := range ps.Conns {
conns = append(conns, conn)
}
ps.ConnMu.Unlock()
for _, conn := range conns {
_ = conn.Close()
}
}