Skip to content

Commit

Permalink
Merge pull request #1115 from jacobbednarz/modernise-workers-kv
Browse files Browse the repository at this point in the history
workers_kv: modernise all methods
  • Loading branch information
jacobbednarz committed Nov 22, 2022
2 parents e051562 + e3a2edf commit 653ee31
Show file tree
Hide file tree
Showing 4 changed files with 257 additions and 193 deletions.
47 changes: 47 additions & 0 deletions .changelog/1115.txt
@@ -0,0 +1,47 @@
```release-note:breaking-change
workers_kv: `CreateWorkersKVNamespace` has been updated to match the experimental client method signatures (https://github.com/cloudflare/cloudflare-go/blob/master/docs/experimental.md).
```

```release-note:breaking-change
workers_kv: `ListWorkersKVNamespaces` has been updated to match the experimental client method signatures (https://github.com/cloudflare/cloudflare-go/blob/master/docs/experimental.md).
```

```release-note:enhancement
workers_kv: `ListWorkersKVNamespaces` automatically paginates all results unless `PerPage` is defined.
```

```release-note:breaking-change
workers_kv: `DeleteWorkersKVNamespace` has been updated to match the experimental client method signatures (https://github.com/cloudflare/cloudflare-go/blob/master/docs/experimental.md).
```

```release-note:breaking-change
workers_kv: `UpdateWorkersKVNamespace` has been updated to match the experimental client method signatures (https://github.com/cloudflare/cloudflare-go/blob/master/docs/experimental.md).
```

```release-note:breaking-change
workers_kv: `WriteWorkersKV` has been renamed to `WriteWorkersKVEntry`.
```

```release-note:breaking-change
workers_kv: `WriteWorkersKVBulk` has been renamed to `WriteWorkersKVEntries`.
```

```release-note:breaking-change
workers_kv: `ReadWorkersKV` has been renamed to `GetWorkersKV`.
```

```release-note:breaking-change
workers_kv: `DeleteWorkersKV` has been renamed to `DeleteWorkersKVEntry`.
```

```release-note:breaking-change
workers_kv: `DeleteWorkersKVBulk` has been renamed to `DeleteWorkersKVEntries`.
```

```release-note:breaking-change
workers_kv: `ListWorkersKVs` has been renamed to `ListWorkersKVKeys`.
```

```release-note:breaking-change
workers_kv: `ListWorkersKVsWithOptions` has been removed. Use `ListWorkersKVKeys` instead and pass in the options.
```
202 changes: 102 additions & 100 deletions workers_kv.go
Expand Up @@ -3,18 +3,21 @@ package cloudflare
import (
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
"net/url"
"strconv"
)

// WorkersKVNamespaceRequest provides parameters for creating and updating storage namespaces.
type WorkersKVNamespaceRequest struct {
// CreateWorkersKVNamespaceParams provides parameters for creating and updating storage namespaces.
type CreateWorkersKVNamespaceParams struct {
Title string `json:"title"`
}

type UpdateWorkersKVNamespaceParams struct {
NamespaceID string `json:"-"`
Title string `json:"title"`
}

// WorkersKVPair is used in an array in the request to the bulk KV api.
type WorkersKVPair struct {
Key string `json:"key"`
Expand All @@ -25,9 +28,6 @@ type WorkersKVPair struct {
Base64 bool `json:"base64,omitempty"`
}

// WorkersKVBulkWriteRequest is the request to the bulk KV api.
type WorkersKVBulkWriteRequest []*WorkersKVPair

// WorkersKVNamespaceResponse is the response received when creating storage namespaces.
type WorkersKVNamespaceResponse struct {
Response
Expand Down Expand Up @@ -55,13 +55,6 @@ type StorageKey struct {
Metadata interface{} `json:"metadata"`
}

// ListWorkersKVsOptions contains optional parameters for listing a namespace's keys.
type ListWorkersKVsOptions struct {
Limit *int
Cursor *string
Prefix *string
}

// ListStorageKeysResponse contains a slice of keys belonging to a storage namespace,
// pagination information, and an embedded response struct.
type ListStorageKeysResponse struct {
Expand All @@ -70,14 +63,51 @@ type ListStorageKeysResponse struct {
ResultInfo `json:"result_info"`
}

type ListWorkersKVNamespacesParams struct {
ResultInfo
}

type WriteWorkersKVEntryParams struct {
NamespaceID string
Key string
Value []byte
}

type WriteWorkersKVEntriesParams struct {
NamespaceID string
KVs []*WorkersKVPair
}

type GetWorkersKVParams struct {
NamespaceID string
Key string
}

type DeleteWorkersKVEntryParams struct {
NamespaceID string
Key string
}

type DeleteWorkersKVEntriesParams struct {
NamespaceID string
Keys []string
}

type ListWorkersKVsParams struct {
NamespaceID string `url:"-"`
Limit int `url:"limit,omitempty"`
Cursor string `url:"cursor,omitempty"`
Prefix string `url:"prefix,omitempty"`
}

// CreateWorkersKVNamespace creates a namespace under the given title.
// A 400 is returned if the account already owns a namespace with this title.
// A namespace must be explicitly deleted to be replaced.
//
// API reference: https://api.cloudflare.com/#workers-kv-namespace-create-a-namespace
func (api *API) CreateWorkersKVNamespace(ctx context.Context, req *WorkersKVNamespaceRequest) (WorkersKVNamespaceResponse, error) {
uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces", api.AccountID)
res, err := api.makeRequestContext(ctx, http.MethodPost, uri, req)
func (api *API) CreateWorkersKVNamespace(ctx context.Context, rc *ResourceContainer, params CreateWorkersKVNamespaceParams) (WorkersKVNamespaceResponse, error) {
uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces", rc.Identifier)
res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params)
if err != nil {
return WorkersKVNamespaceResponse{}, err
}
Expand All @@ -90,49 +120,52 @@ func (api *API) CreateWorkersKVNamespace(ctx context.Context, req *WorkersKVName
return result, err
}

// ListWorkersKVNamespaces lists storage namespaces
// ListWorkersKVNamespaces lists storage namespaces.
//
// API reference: https://api.cloudflare.com/#workers-kv-namespace-list-namespaces
func (api *API) ListWorkersKVNamespaces(ctx context.Context) ([]WorkersKVNamespace, error) {
v := url.Values{}
v.Set("per_page", "100")
func (api *API) ListWorkersKVNamespaces(ctx context.Context, rc *ResourceContainer, params ListWorkersKVNamespacesParams) ([]WorkersKVNamespace, *ResultInfo, error) {
autoPaginate := true
if params.PerPage >= 1 || params.Page >= 1 {
autoPaginate = false
}
if params.PerPage < 1 {
params.PerPage = 50
}
if params.Page < 1 {
params.Page = 1
}

var namespaces []WorkersKVNamespace
page := 1

var nsResponse ListWorkersKVNamespacesResponse
for {
v.Set("page", strconv.Itoa(page))
uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces?%s", api.AccountID, v.Encode())
uri := buildURI(fmt.Sprintf("/accounts/%s/storage/kv/namespaces", rc.Identifier), params)

res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
if err != nil {
return []WorkersKVNamespace{}, err
return []WorkersKVNamespace{}, &ResultInfo{}, err
}

var p ListWorkersKVNamespacesResponse
if err := json.Unmarshal(res, &p); err != nil {
return []WorkersKVNamespace{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
err = json.Unmarshal(res, &nsResponse)
if err != nil {
return []WorkersKVNamespace{}, &ResultInfo{}, fmt.Errorf("failed to unmarshal workers KV namespaces JSON data: %w", err)
}

if !p.Success {
return []WorkersKVNamespace{}, errors.New(errRequestNotSuccessful)
}
namespaces = append(namespaces, nsResponse.Result...)
params.ResultInfo = nsResponse.ResultInfo.Next()

namespaces = append(namespaces, p.Result...)
if p.ResultInfo.Page >= p.ResultInfo.TotalPages {
if params.ResultInfo.Done() || !autoPaginate {
break
}

page++
}

return namespaces, nil
return namespaces, &nsResponse.ResultInfo, nil
}

// DeleteWorkersKVNamespace deletes the namespace corresponding to the given ID
// DeleteWorkersKVNamespace deletes the namespace corresponding to the given ID.
//
// API reference: https://api.cloudflare.com/#workers-kv-namespace-remove-a-namespace
func (api *API) DeleteWorkersKVNamespace(ctx context.Context, namespaceID string) (Response, error) {
uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s", api.AccountID, namespaceID)
func (api *API) DeleteWorkersKVNamespace(ctx context.Context, rc *ResourceContainer, namespaceID string) (Response, error) {
uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s", rc.Identifier, namespaceID)
res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil)
if err != nil {
return Response{}, err
Expand All @@ -146,12 +179,12 @@ func (api *API) DeleteWorkersKVNamespace(ctx context.Context, namespaceID string
return result, err
}

// UpdateWorkersKVNamespace modifies a namespace's title
// UpdateWorkersKVNamespace modifies a KV namespace based on the ID.
//
// API reference: https://api.cloudflare.com/#workers-kv-namespace-rename-a-namespace
func (api *API) UpdateWorkersKVNamespace(ctx context.Context, namespaceID string, req *WorkersKVNamespaceRequest) (Response, error) {
uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s", api.AccountID, namespaceID)
res, err := api.makeRequestContext(ctx, http.MethodPut, uri, req)
func (api *API) UpdateWorkersKVNamespace(ctx context.Context, rc *ResourceContainer, params UpdateWorkersKVNamespaceParams) (Response, error) {
uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s", rc.Identifier, params.NamespaceID)
res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params)
if err != nil {
return Response{}, err
}
Expand All @@ -164,14 +197,13 @@ func (api *API) UpdateWorkersKVNamespace(ctx context.Context, namespaceID string
return result, err
}

// WriteWorkersKV writes a value identified by a key.
// WriteWorkersKVEntry writes a single KV value based on the key.
//
// API reference: https://api.cloudflare.com/#workers-kv-namespace-write-key-value-pair
func (api *API) WriteWorkersKV(ctx context.Context, namespaceID, key string, value []byte) (Response, error) {
key = url.PathEscape(key)
uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s/values/%s", api.AccountID, namespaceID, key)
func (api *API) WriteWorkersKVEntry(ctx context.Context, rc *ResourceContainer, params WriteWorkersKVEntryParams) (Response, error) {
uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s/values/%s", rc.Identifier, params.NamespaceID, url.PathEscape(params.Key))
res, err := api.makeRequestContextWithHeaders(
ctx, http.MethodPut, uri, value, http.Header{"Content-Type": []string{"application/octet-stream"}},
ctx, http.MethodPut, uri, params.Value, http.Header{"Content-Type": []string{"application/octet-stream"}},
)
if err != nil {
return Response{}, err
Expand All @@ -185,13 +217,13 @@ func (api *API) WriteWorkersKV(ctx context.Context, namespaceID, key string, val
return result, err
}

// WriteWorkersKVBulk writes multiple KVs at once.
// WriteWorkersKVEntries writes multiple KVs at once.
//
// API reference: https://api.cloudflare.com/#workers-kv-namespace-write-multiple-key-value-pairs
func (api *API) WriteWorkersKVBulk(ctx context.Context, namespaceID string, kvs WorkersKVBulkWriteRequest) (Response, error) {
uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s/bulk", api.AccountID, namespaceID)
func (api *API) WriteWorkersKVEntries(ctx context.Context, rc *ResourceContainer, params WriteWorkersKVEntriesParams) (Response, error) {
uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s/bulk", rc.Identifier, params.NamespaceID)
res, err := api.makeRequestContextWithHeaders(
ctx, http.MethodPut, uri, kvs, http.Header{"Content-Type": []string{"application/json"}},
ctx, http.MethodPut, uri, params.KVs, http.Header{"Content-Type": []string{"application/json"}},
)
if err != nil {
return Response{}, err
Expand All @@ -205,25 +237,24 @@ func (api *API) WriteWorkersKVBulk(ctx context.Context, namespaceID string, kvs
return result, err
}

// ReadWorkersKV returns the value associated with the given key in the given namespace
// GetWorkersKV returns the value associated with the given key in the
// given namespace.
//
// API reference: https://api.cloudflare.com/#workers-kv-namespace-read-key-value-pair
func (api API) ReadWorkersKV(ctx context.Context, namespaceID, key string) ([]byte, error) {
key = url.PathEscape(key)
uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s/values/%s", api.AccountID, namespaceID, key)
func (api API) GetWorkersKV(ctx context.Context, rc *ResourceContainer, params GetWorkersKVParams) ([]byte, error) {
uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s/values/%s", rc.Identifier, params.NamespaceID, url.PathEscape(params.Key))
res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
return res, nil
}

// DeleteWorkersKV deletes a key and value for a provided storage namespace
// DeleteWorkersKVEntry deletes a key and value for a provided storage namespace.
//
// API reference: https://api.cloudflare.com/#workers-kv-namespace-delete-key-value-pair
func (api API) DeleteWorkersKV(ctx context.Context, namespaceID, key string) (Response, error) {
key = url.PathEscape(key)
uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s/values/%s", api.AccountID, namespaceID, key)
func (api API) DeleteWorkersKVEntry(ctx context.Context, rc *ResourceContainer, params DeleteWorkersKVEntryParams) (Response, error) {
uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s/values/%s", rc.Identifier, params.NamespaceID, url.PathEscape(params.Key))
res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil)
if err != nil {
return Response{}, err
Expand All @@ -236,13 +267,13 @@ func (api API) DeleteWorkersKV(ctx context.Context, namespaceID, key string) (Re
return result, err
}

// DeleteWorkersKVBulk deletes multiple KVs at once.
// DeleteWorkersKVEntries deletes multiple KVs at once.
//
// API reference: https://api.cloudflare.com/#workers-kv-namespace-delete-multiple-key-value-pairs
func (api *API) DeleteWorkersKVBulk(ctx context.Context, namespaceID string, keys []string) (Response, error) {
uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s/bulk", api.AccountID, namespaceID)
func (api *API) DeleteWorkersKVEntries(ctx context.Context, rc *ResourceContainer, params DeleteWorkersKVEntriesParams) (Response, error) {
uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s/bulk", rc.Identifier, params.NamespaceID)
res, err := api.makeRequestContextWithHeaders(
ctx, http.MethodDelete, uri, keys, http.Header{"Content-Type": []string{"application/json"}},
ctx, http.MethodDelete, uri, params.Keys, http.Header{"Content-Type": []string{"application/json"}},
)
if err != nil {
return Response{}, err
Expand All @@ -256,43 +287,14 @@ func (api *API) DeleteWorkersKVBulk(ctx context.Context, namespaceID string, key
return result, err
}

// ListWorkersKVs lists a namespace's keys
// ListWorkersKVKeys lists a namespace's keys.
//
// API Reference: https://api.cloudflare.com/#workers-kv-namespace-list-a-namespace-s-keys
func (api API) ListWorkersKVs(ctx context.Context, namespaceID string) (ListStorageKeysResponse, error) {
uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s/keys", api.AccountID, namespaceID)
res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
if err != nil {
return ListStorageKeysResponse{}, err
}

result := ListStorageKeysResponse{}
if err := json.Unmarshal(res, &result); err != nil {
return result, fmt.Errorf("%s: %w", errUnmarshalError, err)
}
return result, err
}

// encode encodes non-nil fields into URL encoded form.
func (o ListWorkersKVsOptions) encode() string {
v := url.Values{}
if o.Limit != nil {
v.Set("limit", strconv.Itoa(*o.Limit))
}
if o.Cursor != nil {
v.Set("cursor", *o.Cursor)
}
if o.Prefix != nil {
v.Set("prefix", *o.Prefix)
}
return v.Encode()
}

// ListWorkersKVsWithOptions lists a namespace's keys with optional parameters
//
// API Reference: https://api.cloudflare.com/#workers-kv-namespace-list-a-namespace-s-keys
func (api API) ListWorkersKVsWithOptions(ctx context.Context, namespaceID string, o ListWorkersKVsOptions) (ListStorageKeysResponse, error) {
uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s/keys?%s", api.AccountID, namespaceID, o.encode())
func (api API) ListWorkersKVKeys(ctx context.Context, rc *ResourceContainer, params ListWorkersKVsParams) (ListStorageKeysResponse, error) {
uri := buildURI(
fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s/keys", rc.Identifier, params.NamespaceID),
params,
)
res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
if err != nil {
return ListStorageKeysResponse{}, err
Expand Down

0 comments on commit 653ee31

Please sign in to comment.