main
1package snapshot
2
3import (
4 "io"
5 "time"
6)
7
8type BodySink struct {
9 io.WriteCloser
10 Path string
11}
12
13type options struct {
14 UserAgent string
15 Timeout time.Duration
16 BodySink func() (BodySink, error)
17}
18
19type Option interface {
20 apply(*options)
21}
22
23func defaults() *options {
24 return &options{
25 UserAgent: "Mozilla/5.0 (X11; Linux x86_64; rv:120.0) Gecko/20100101 Firefox/120.0",
26 Timeout: 10 * time.Second,
27 BodySink: func() (BodySink, error) {
28 return BodySink{
29 WriteCloser: nopClose{io.Discard},
30 Path: "",
31 }, nil
32 },
33 }
34}
35
36type bodyPathOption string
37type bodySinkOption struct {
38 io.WriteCloser
39 Path string
40}
41
42// Capture will write the raw response bytes to provided path and close the file
43func WithBodyPath(path string) Option { return bodyPathOption(path) }
44func (bpo bodyPathOption) apply(o *options) {
45 path := string(bpo)
46 f := func() (BodySink, error) {
47 w, err := newAtomicFileWriter(path)
48 if err != nil {
49 return BodySink{}, err
50 }
51 return BodySink{
52 WriteCloser: w,
53 Path: path,
54 }, nil
55 }
56 o.BodySink = f
57}
58
59// Capture will write the raw response bytes to the provided io.WriteCloser and call Close
60// path is only used to record where the body was written in Capture's Result, leave empty to omit
61func WithBodySink(w io.WriteCloser, path string) Option {
62 return bodySinkOption{WriteCloser: w, Path: path}
63}
64func (bso bodySinkOption) apply(o *options) {
65 o.BodySink = func() (BodySink, error) {
66 return BodySink{
67 WriteCloser: bso.WriteCloser,
68 Path: bso.Path}, nil
69 }
70}
71
72// helper to create a io.NopCloser(io.Writer)
73type nopClose struct{ io.Writer }
74
75func (nopClose) Close() error { return nil }