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
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user