burterm/internal/proxy/store.go
2026-09-14 10:55:07 +03:00

77 lines
2.8 KiB
Go

package proxy
import (
"net/http"
"sync"
"time"
)
// Entry — одна перехваченная транзакция запрос/ответ, готовая к показу
// в TUI и (по Raw) к загрузке прямо в Request Builder.
type Entry struct {
ID int
Timestamp time.Time
Method string
URL string
Raw string // сырой HTTP-запрос целиком — то, что вставляется в §маркеры§ форму
StatusCode int
Length int64
Headers http.Header // заголовки ответа — для цветовой маркировки по Content-Type в TUI
ResponseBody string // тело ответа, обрезанное до maxResponseCapture байт — для полнотекстового поиска в Project
Err error // не nil, если запрос не удалось выполнить (таймаут, обрыв соединения и т.п.)
}
// Store хранит историю перехваченных запросов и рассылает новые записи
// подписчикам (обычно единственный подписчик — TUI) через каналы.
type Store struct {
mu sync.Mutex
entries []Entry
nextID int
subs []chan Entry
}
// NewStore создаёт пустое хранилище.
func NewStore() *Store {
return &Store{}
}
// Add сохраняет запись, присваивает ей ID и рассылает подписчикам.
// Рассылка неблокирующая: если подписчик не успевает вычитывать канал,
// запись всё равно остаётся в общей истории (доступна через All),
// прокси-сервер из-за медленного TUI не подвиснет.
func (s *Store) Add(e Entry) Entry {
s.mu.Lock()
s.nextID++
e.ID = s.nextID
s.entries = append(s.entries, e)
subs := append([]chan Entry(nil), s.subs...)
s.mu.Unlock()
for _, ch := range subs {
select {
case ch <- e:
default:
}
}
return e
}
// All возвращает копию текущей истории — используется для первичной
// загрузки TUI при старте, если прокси уже что-то успел перехватить.
func (s *Store) All() []Entry {
s.mu.Lock()
defer s.mu.Unlock()
out := make([]Entry, len(s.entries))
copy(out, s.entries)
return out
}
// Subscribe возвращает канал, в который будут падать все новые записи,
// добавленные после момента подписки.
func (s *Store) Subscribe() <-chan Entry {
ch := make(chan Entry, 64)
s.mu.Lock()
s.subs = append(s.subs, ch)
s.mu.Unlock()
return ch
}