diff --git a/config/config.go b/config/config.go index 3dcc501..3109e86 100644 --- a/config/config.go +++ b/config/config.go @@ -30,6 +30,7 @@ func (d *Duration) UnmarshalText(text []byte) error { type Config struct { General GeneralOptions + Meta MetaOptions Keys map[string]map[string]string } @@ -39,11 +40,16 @@ type GeneralOptions struct { Insecure bool PreserveScrollPosition bool FollowRedirects bool + PersistHistory bool DefaultURLScheme string TLSVersionMin uint16 TLSVersionMax uint16 } +type MetaOptions struct { + ConfigLocation string +} + var defaultTimeoutDuration, _ = time.ParseDuration("1m") var DefaultKeys = map[string]map[string]string{ @@ -98,8 +104,12 @@ var DefaultConfig = Config{ Insecure: false, PreserveScrollPosition: true, FollowRedirects: true, + PersistHistory: false, DefaultURLScheme: "https", }, + Meta: MetaOptions{ + ConfigLocation: "", + }, } func LoadConfig(configFile string) (*Config, error) { @@ -114,6 +124,8 @@ func LoadConfig(configFile string) (*Config, error) { return nil, err } + conf.Meta.ConfigLocation = configFile + if conf.Keys == nil { conf.Keys = DefaultKeys } else { diff --git a/wuzz.go b/wuzz.go index 9289ad6..13a75d8 100644 --- a/wuzz.go +++ b/wuzz.go @@ -4,6 +4,7 @@ import ( "bytes" "compress/gzip" "crypto/tls" + "encoding/json" "errors" "fmt" "io" @@ -12,6 +13,7 @@ import ( "net/http" "net/url" "os" + "path/filepath" "regexp" "runtime" "sort" @@ -785,6 +787,7 @@ func (a *App) SubmitRequest(g *gocui.Gui, _ *gocui.View) error { // add to history a.history = append(a.history, r) a.historyIndex = len(a.history) - 1 + a.SaveHistory() // render response g.Execute(func(g *gocui.Gui) error { @@ -1124,6 +1127,72 @@ func (a *App) CreatePopupView(name string, width, height int, g *gocui.Gui) (v * return } +func (a *App) SerializeHistory() ([]byte, error) { + return json.Marshal(a.history) +} + +func (a *App) DeserializeHistory(input []byte) ([]*Request, error) { + history := []*Request{} + err := json.Unmarshal(input, &history) + return history, err +} + +func (a *App) GetHistoryFile() (string, error) { + if a.config.Meta.ConfigLocation == "" { + return "", errors.New("There is no known config directory.") + } + dir := filepath.Dir(a.config.Meta.ConfigLocation) + histFile := filepath.Join(dir, "history.json") + return histFile, nil +} + +func (a *App) SaveHistory() error { + if !a.config.General.PersistHistory { + return nil + } + + histFile, err := a.GetHistoryFile() + if err != nil { + return err + } + + serializedHistory, err := a.SerializeHistory() + if err != nil { + return err + } + + err = ioutil.WriteFile(histFile, serializedHistory, 0644) + if err != nil { + return err + } + + return nil +} + +func (a *App) LoadHistory() error { + if !a.config.General.PersistHistory { + return nil + } + + histFile, err := a.GetHistoryFile() + if err != nil { + return err + } + + histBytes, err := ioutil.ReadFile(histFile) + if err != nil { + return err + } + + history, err := a.DeserializeHistory(histBytes) + if err != nil { + return err + } + + a.history = history + return nil +} + func (a *App) ToggleHistory(g *gocui.Gui, _ *gocui.View) (err error) { // Destroy if present if a.currentPopup == HISTORY_VIEW { @@ -1604,6 +1673,15 @@ func main() { os.Exit(1) } + if app.config.General.PersistHistory { + err = app.LoadHistory() + if err != nil && !os.IsNotExist(err) { + g.Close() + fmt.Println("Error!", err) + os.Exit(1) + } + } + defer g.Close() if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {