Skip to content

Commit

Permalink
feat(api): update via SDK Studio (#1616)
Browse files Browse the repository at this point in the history
  • Loading branch information
stainless-app[bot] committed Mar 27, 2024
1 parent 94833ff commit 15efe89
Show file tree
Hide file tree
Showing 11 changed files with 889 additions and 196 deletions.
2 changes: 1 addition & 1 deletion .stats.yml
@@ -1 +1 @@
configured_endpoints: 1290
configured_endpoints: 1292
13 changes: 13 additions & 0 deletions README.md
Expand Up @@ -244,6 +244,19 @@ client.Zones.Edit(
)
```

### File uploads

Request parameters that correspond to file uploads in multipart requests are typed as
`param.Field[io.Reader]`. The contents of the `io.Reader` will by default be sent as a multipart form
part with the file name of "anonymous_file" and content-type of "application/octet-stream".

The file name and content-type can be customized by implementing `Name() string` or `ContentType()
string` on the run-time type of `io.Reader`. Note that `os.File` implements `Name() string`, so a
file returned by `os.Open` will be sent with the file name on disk.

We also provide a helper `cloudflare.FileParam(reader io.Reader, filename string, contentType string)`
which can be used to wrap any `io.Reader` with the appropriate file name and content type.

## Retries

Certain errors will be automatically retried 2 times by default, with a short exponential backoff.
Expand Down
43 changes: 28 additions & 15 deletions api.md

Large diffs are not rendered by default.

17 changes: 16 additions & 1 deletion field.go
Expand Up @@ -2,6 +2,7 @@ package cloudflare

import (
"github.com/cloudflare/cloudflare-go/v2/internal/param"
"io"
)

// F is a param field helper used to initialize a [param.Field] generic struct.
Expand All @@ -11,7 +12,7 @@ import (
// [README]: https://pkg.go.dev/github.com/cloudflare/cloudflare-go/v2#readme-request-fields
func F[T any](value T) param.Field[T] { return param.Field[T]{Value: value, Present: true} }

// Null is a param field helper which explciitly sends null to the API.
// Null is a param field helper which explicitly sends null to the API.
func Null[T any]() param.Field[T] { return param.Field[T]{Null: true, Present: true} }

// Raw is a param field helper for specifying values for fields when the
Expand All @@ -33,3 +34,17 @@ func Float(value float64) param.Field[float64] { return F(value) }

// Bool is a param field helper which helps specify bools.
func Bool(value bool) param.Field[bool] { return F(value) }

// FileParam is a param field helper which helps files with a mime content-type.
func FileParam(reader io.Reader, filename string, contentType string) param.Field[io.Reader] {
return F[io.Reader](&file{reader, filename, contentType})
}

type file struct {
io.Reader
name string
contentType string
}

func (f *file) Name() string { return f.name }
func (f *file) ContentType() string { return f.contentType }
24 changes: 22 additions & 2 deletions internal/apiform/encoder.go
Expand Up @@ -4,10 +4,12 @@ import (
"fmt"
"io"
"mime/multipart"
"net/textproto"
"path"
"reflect"
"sort"
"strconv"
"strings"
"sync"
"time"

Expand Down Expand Up @@ -302,15 +304,33 @@ func (e encoder) newInterfaceEncoder() encoderFunc {
}
}

var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"")

func escapeQuotes(s string) string {
return quoteEscaper.Replace(s)
}

func (e *encoder) newReaderTypeEncoder() encoderFunc {
return func(key string, value reflect.Value, writer *multipart.Writer) error {
reader := value.Convert(reflect.TypeOf((*io.Reader)(nil)).Elem()).Interface().(io.Reader)
filename := "anonymous_file"
contentType := "application/octet-stream"
if named, ok := reader.(interface{ Name() string }); ok {
filename = path.Base(named.Name())
}
filewriter, err := writer.CreateFormFile(key, filename)
io.Copy(filewriter, reader)
if typed, ok := reader.(interface{ ContentType() string }); ok {
contentType = path.Base(typed.ContentType())
}

// Below is taken almost 1-for-1 from [multipart.CreateFormFile]
h := make(textproto.MIMEHeader)
h.Set("Content-Disposition", fmt.Sprintf(`form-data; name="%s"; filename="%s"`, escapeQuotes(key), escapeQuotes(filename)))
h.Set("Content-Type", contentType)
filewriter, err := writer.CreatePart(h)
if err != nil {
return err
}
_, err = io.Copy(filewriter, reader)
return err
}
}
Expand Down

0 comments on commit 15efe89

Please sign in to comment.