-
Notifications
You must be signed in to change notification settings - Fork 2
/
estuary.go
87 lines (71 loc) · 2 KB
/
estuary.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package main
import (
"bytes"
"fmt"
"io"
"net/http"
"os"
"strconv"
)
const (
envEstuaryKeyKey = "ESTUARY_KEY"
envEstuaryShuttleKey = "ESTUARY_SHUTTLE"
)
var estuaryDriverCreator = driverCreator{
factory: newEstuaryDriver,
help: estuaryHelp,
maxCarSize: 31*1024*1024*1024 + 1024*1024*512, // 31GiB512MiB
}
func estuaryHelp(out io.Writer) {
fmt.Fprint(out, ` Environ:
- `+envEstuaryKeyKey+` estuary API key
- `+envEstuaryShuttleKey+` shuttle domain
`)
}
func newEstuaryDriver(input string) (driver, error) {
if input != "" {
return nil, fmt.Errorf("non empty estuary argument: %q", input)
}
key := os.Getenv(envEstuaryKeyKey)
shuttle := os.Getenv(envEstuaryShuttleKey)
if key == "" {
return nil, fmt.Errorf("error empty " + envEstuaryKeyKey + " envKey")
}
if shuttle == "" {
return nil, fmt.Errorf("error empty " + envEstuaryShuttleKey + " envKey")
}
d := &estuaryDriver{
key: key,
shuttle: "https://" + shuttle + "/content/add-car",
}
return d.send, nil
}
type estuaryDriver struct {
shuttle string
key string
client http.Client
}
func (e *estuaryDriver) send(headerBuffer []byte, car *os.File, carOffset int64) error {
_, err := car.Seek(carOffset, io.SeekStart)
if err != nil {
return fmt.Errorf("error seeking temp file: %w", err)
}
req, err := http.NewRequest("POST", e.shuttle, io.MultiReader(bytes.NewReader(headerBuffer), car))
if err != nil {
return fmt.Errorf("creating the request failed: %w", err)
}
req.Header.Set("User-Agent", userAgent)
req.Header.Set("Content-Type", "application/vnd.ipld.car")
req.Header.Set("Authorization", "Bearer "+e.key)
req.Header.Set("Content-Length", strconv.FormatUint(uint64(int64(len(headerBuffer))+carMaxSize-carOffset), 10))
resp, err := e.client.Do(req)
if err != nil {
return fmt.Errorf("posting failed: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
b, _ := io.ReadAll(resp.Body)
return fmt.Errorf("non 200 result code: %d / body: %s", resp.StatusCode, string(b))
}
return nil
}