-
Notifications
You must be signed in to change notification settings - Fork 123
/
shared.go
149 lines (127 loc) · 3.23 KB
/
shared.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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package main
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
)
type httpHeader http.Header
const (
defaultEmptyMessagesLimit uint = 300
)
// ErrTooManyEmptyStreamMessages represents an error when a stream has sent too many empty messages.
var ErrTooManyEmptyStreamMessages = errors.New("stream has sent too many empty messages")
// Marshaller is an interface for marshalling values to bytes.
type Marshaller interface {
Marshal(value any) ([]byte, error)
}
// JSONMarshaller is a marshaller that marshals values to JSON.
type JSONMarshaller struct{}
// Marshal marshals a value to JSON.
func (jm *JSONMarshaller) Marshal(value any) ([]byte, error) {
result, err := json.Marshal(value)
if err != nil {
return result, fmt.Errorf("JSONMarshaller.Marshal: %w", err)
}
return result, nil
}
// HTTPRequestBuilder is an implementation of OllamaRequestBuilder that builds HTTP requests.
type HTTPRequestBuilder struct {
marshaller Marshaller
}
// Build builds an HTTP request.
func (b *HTTPRequestBuilder) Build(
ctx context.Context,
method string,
url string,
body any,
header http.Header,
) (req *http.Request, err error) {
var bodyReader io.Reader
if body != nil {
if v, ok := body.(io.Reader); ok {
bodyReader = v
} else {
var reqBytes []byte
reqBytes, err = b.marshaller.Marshal(body)
if err != nil {
return
}
bodyReader = bytes.NewBuffer(reqBytes)
}
}
req, err = http.NewRequestWithContext(ctx, method, url, bodyReader)
if err != nil {
return
}
if header != nil {
req.Header = header
}
return
}
type requestOptions struct {
body any
header http.Header
}
type requestOption func(*requestOptions)
func withBody(body any) requestOption {
return func(args *requestOptions) {
args.body = body
}
}
// ErrorAccumulator is an interface for accumulating errors.
type ErrorAccumulator interface {
Write(p []byte) error
Bytes() []byte
}
// Unmarshaler is an interface for unmarshalling bytes.
type Unmarshaler interface {
Unmarshal(data []byte, v any) error
}
type errorBuffer interface {
io.Writer
Len() int
Bytes() []byte
}
// DefaultErrorAccumulator is a default implementation of ErrorAccumulator.
type DefaultErrorAccumulator struct {
Buffer errorBuffer
}
// NewErrorAccumulator creates a new ErrorAccumulator.
func NewErrorAccumulator() ErrorAccumulator {
return &DefaultErrorAccumulator{
Buffer: &bytes.Buffer{},
}
}
// Write writes data to the error accumulator.
func (e *DefaultErrorAccumulator) Write(p []byte) error {
_, err := e.Buffer.Write(p)
if err != nil {
return fmt.Errorf("error accumulator write error, %w", err)
}
return nil
}
// Bytes returns the accumulated error bytes.
func (e *DefaultErrorAccumulator) Bytes() (errBytes []byte) {
if e.Buffer.Len() == 0 {
return
}
errBytes = e.Buffer.Bytes()
return
}
func isFailureStatusCode(resp *http.Response) bool {
return resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusBadRequest
}
// JSONUnmarshaler is an unmarshaler that unmarshals JSON data.
type JSONUnmarshaler struct{}
// Unmarshal unmarshals JSON data.
func (jm *JSONUnmarshaler) Unmarshal(data []byte, v any) error {
err := json.Unmarshal(data, v)
if err != nil {
return fmt.Errorf("JSONUnmarshaler.Unmarshal: %w", err)
}
return nil
}