Files
owenandClaude Sonnet 5 ba1f7c4c03 Initial vibeproxy implementation
Self-contained HTTP/HTTPS/TCP/UDP reverse proxy manager written in Go,
with SQLite storage, a Bootstrap 5 admin UI (Go templates, no JS
framework), and a REST API under /api/v1.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QTXFrNP1imCW7jtfL5SZrw
2026-08-17 10:28:59 -05:00

86 lines
2.8 KiB
Go

package database
import (
"database/sql"
"errors"
"github.com/owen/vibeproxy/internal/models"
)
func scanStream(rs rowScanner) (models.Stream, error) {
var s models.Stream
var proxyProto, enabled int
var created, updated string
err := rs.Scan(&s.ID, &s.Protocol, &s.ListenIP, &s.ListenPort, &s.DestinationHost, &s.DestinationPort,
&s.ConnectTimeoutMS, &s.IdleTimeoutMS, &proxyProto, &enabled, &s.Comments, &created, &updated)
if err != nil {
return s, err
}
s.ProxyProtocol = proxyProto == 1
s.Enabled = enabled == 1
s.CreatedAt = parseTime(created)
s.UpdatedAt = parseTime(updated)
return s, nil
}
const streamCols = `id, protocol, listen_ip, listen_port, destination_host, destination_port, connect_timeout_ms, idle_timeout_ms, proxy_protocol, enabled, comments, created_at, updated_at`
func ListStreams(db *sql.DB) ([]models.Stream, error) {
rows, err := db.Query(`SELECT ` + streamCols + ` FROM streams ORDER BY id`)
if err != nil {
return nil, err
}
defer rows.Close()
var out []models.Stream
for rows.Next() {
s, err := scanStream(rows)
if err != nil {
return nil, err
}
out = append(out, s)
}
return out, rows.Err()
}
func GetStream(db *sql.DB, id int64) (*models.Stream, error) {
row := db.QueryRow(`SELECT `+streamCols+` FROM streams WHERE id = ?`, id)
s, err := scanStream(row)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, ErrNotFound
}
return nil, err
}
return &s, nil
}
func SaveStream(db *sql.DB, s *models.Stream) (int64, error) {
if s.ID == 0 {
res, err := db.Exec(`INSERT INTO streams (protocol, listen_ip, listen_port, destination_host, destination_port,
connect_timeout_ms, idle_timeout_ms, proxy_protocol, enabled, comments) VALUES (?,?,?,?,?,?,?,?,?,?)`,
s.Protocol, s.ListenIP, s.ListenPort, s.DestinationHost, s.DestinationPort, s.ConnectTimeoutMS,
s.IdleTimeoutMS, boolToInt(s.ProxyProtocol), boolToInt(s.Enabled), s.Comments)
if err != nil {
return 0, err
}
id, err := res.LastInsertId()
s.ID = id
return id, err
}
_, err := db.Exec(`UPDATE streams SET protocol=?, listen_ip=?, listen_port=?, destination_host=?, destination_port=?,
connect_timeout_ms=?, idle_timeout_ms=?, proxy_protocol=?, enabled=?, comments=?, updated_at=strftime('%Y-%m-%dT%H:%M:%fZ','now')
WHERE id=?`, s.Protocol, s.ListenIP, s.ListenPort, s.DestinationHost, s.DestinationPort, s.ConnectTimeoutMS,
s.IdleTimeoutMS, boolToInt(s.ProxyProtocol), boolToInt(s.Enabled), s.Comments, s.ID)
return s.ID, err
}
func DeleteStream(db *sql.DB, id int64) error {
_, err := db.Exec(`DELETE FROM streams WHERE id = ?`, id)
return err
}
func SetStreamEnabled(db *sql.DB, id int64, enabled bool) error {
_, err := db.Exec(`UPDATE streams SET enabled = ?, updated_at = strftime('%Y-%m-%dT%H:%M:%fZ','now') WHERE id = ?`, boolToInt(enabled), id)
return err
}