package cmd
import (
"context"
"fmt"
"os"
"time"
"github.com/spf13/cobra"
"mercemay.top/httptap/internal/export/curl"
"mercemay.top/httptap/internal/export/har"
"mercemay.top/httptap/internal/export/markdown"
"mercemay.top/httptap/internal/export/raw"
"mercemay.top/httptap/internal/parser"
"mercemay.top/httptap/internal/source"
)
type exportFlags struct {
Format string
Output string
Input string
}
func newExportCmd() *cobra.Command {
var ef exportFlags
cmd := &cobra.Command{
Use: "export",
Short: "Convert a capture file to another format",
RunE: func(c *cobra.Command, args []string) error {
return runExport(ef)
},
}
cmd.Flags().StringVarP(&ef.Format, "format", "f", "har",
"one of har|curl|raw|markdown")
cmd.Flags().StringVarP(&ef.Output, "output", "o", "-",
"destination path, '-' for stdout")
cmd.Flags().StringVarP(&ef.Input, "input", "i", "",
"source capture file (HAR or raw)")
_ = cmd.MarkFlagRequired("input")
return cmd
}
func runExport(ef exportFlags) error {
src, err := source.OpenFile(ef.Input)
if err != nil {
return err
}
defer src.Close()
out := os.Stdout
if ef.Output != "-" {
out, err = os.Create(ef.Output)
if err != nil {
return err
}
defer out.Close()
}
// Collect every message, then render in one pass.
var msgs []parser.Message
ctx := context.Background()
for {
ev, err := src.Next(ctx)
if err != nil {
break
}
p := parser.New(bytesReader(ev.Payload), func(m parser.Message) {
msgs = append(msgs, m)
})
_ = p.Run()
}
switch ef.Format {
case "har":
entries := make([]har.Entry, 0, len(msgs)/2)
for i := 0; i+1 < len(msgs); i += 2 {
entries = append(entries, har.FromPair(msgs[i], msgs[i+1], time.Now(), 0))
}
return har.Write(out, entries)
case "curl":
for _, m := range msgs {
fmt.Fprintln(out, curl.RenderPretty(m))
}
case "raw":
for _, m := range msgs {
if err := raw.WriteMessage(out, m); err != nil {
return err
}
}
case "markdown":
for i := 0; i+1 < len(msgs); i += 2 {
_ = markdown.Write(out, msgs[i], msgs[i+1], time.Now(), 0, markdown.Default())
}
default:
return fmt.Errorf("export: unknown format %q", ef.Format)
}
return nil
}