Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WC-1473: Add support for script content and script settings read/update endpoints #1361

Merged
merged 6 commits into from
Aug 22, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changelog/1361.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```release-note:enhancement
workers: Add support for retrieving and uploading only script content.
```

```release-note:enhancement
workers: Add support for retrieving and uploading only script metadata.
```
195 changes: 191 additions & 4 deletions workers.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,49 @@ type CreateWorkerParams struct {
Placement *Placement
}

type UpdateWorkersScriptContentParams struct {
ScriptName string
Script string

// DispatchNamespaceName uploads the worker to a WFP dispatch namespace if provided
DispatchNamespaceName *string

// Module changes the Content-Type header to specify the script is an
// ES Module syntax script.
Module bool
}

type UpdateWorkersScriptSettingsParams struct {
ScriptName string

// Logpush opts the worker into Workers Logpush logging. A nil value leaves
// the current setting unchanged.
//
// Documentation: https://developers.cloudflare.com/workers/platform/logpush/
Logpush *bool

// TailConsumers specifies a list of Workers that will consume the logs of
// the attached Worker.
// Documentation: https://developers.cloudflare.com/workers/platform/tail-workers/
TailConsumers *[]WorkersTailConsumer

// Bindings should be a map where the keys are the binding name, and the
// values are the binding content
Bindings map[string]WorkerBinding

// CompatibilityDate is a date in the form yyyy-mm-dd,
// which will be used to determine which version of the Workers runtime is used.
// https://developers.cloudflare.com/workers/platform/compatibility-dates/
CompatibilityDate string

// CompatibilityFlags are the names of features of the Workers runtime to be enabled or disabled,
// usually used together with CompatibilityDate.
// https://developers.cloudflare.com/workers/platform/compatibility-dates/#compatibility-flags
CompatibilityFlags []string

Placement *Placement
}

// WorkerScriptParams provides a worker script and the associated bindings.
type WorkerScriptParams struct {
ScriptName string
Expand Down Expand Up @@ -134,6 +177,12 @@ type WorkerScriptResponse struct {
WorkerScript `json:"result"`
}

// WorkerScriptSettingsResponse wrapper struct for API response to worker script settings calls.
type WorkerScriptSettingsResponse struct {
Response
WorkerMetaData
}

type ListWorkersParams struct{}

type DeleteWorkerParams struct {
Expand All @@ -153,7 +202,7 @@ type Placement struct {

// DeleteWorker deletes a single Worker.
//
// API reference: https://api.cloudflare.com/#worker-script-delete-worker
// API reference: https://developers.cloudflare.com/api/operations/worker-script-delete-worker
func (api *API) DeleteWorker(ctx context.Context, rc *ResourceContainer, params DeleteWorkerParams) error {
if rc.Level != AccountRouteLevel {
return ErrRequiredAccountLevelResourceContainer
Expand Down Expand Up @@ -182,7 +231,7 @@ func (api *API) DeleteWorker(ctx context.Context, rc *ResourceContainer, params
// GetWorker fetch raw script content for your worker returns string containing
// worker code js.
//
// API reference: https://developers.cloudflare.com/workers/tooling/api/scripts/
// API reference: https://developers.cloudflare.com/api/operations/worker-script-download-worker
func (api *API) GetWorker(ctx context.Context, rc *ResourceContainer, scriptName string) (WorkerScriptResponse, error) {
if rc.Level != AccountRouteLevel {
return WorkerScriptResponse{}, ErrRequiredAccountLevelResourceContainer
Expand Down Expand Up @@ -225,7 +274,7 @@ func (api *API) GetWorker(ctx context.Context, rc *ResourceContainer, scriptName

// ListWorkers returns list of Workers for given account.
//
// API reference: https://developers.cloudflare.com/workers/tooling/api/scripts/
// API reference: https://developers.cloudflare.com/api/operations/worker-script-list-workers
func (api *API) ListWorkers(ctx context.Context, rc *ResourceContainer, params ListWorkersParams) (WorkerListResponse, *ResultInfo, error) {
if rc.Level != AccountRouteLevel {
return WorkerListResponse{}, &ResultInfo{}, ErrRequiredAccountLevelResourceContainer
Expand All @@ -252,7 +301,7 @@ func (api *API) ListWorkers(ctx context.Context, rc *ResourceContainer, params L

// UploadWorker pushes raw script content for your Worker.
//
// API reference: https://api.cloudflare.com/#worker-script-upload-worker
// API reference: https://developers.cloudflare.com/api/operations/worker-script-upload-worker-module
func (api *API) UploadWorker(ctx context.Context, rc *ResourceContainer, params CreateWorkerParams) (WorkerScriptResponse, error) {
if rc.Level != AccountRouteLevel {
return WorkerScriptResponse{}, ErrRequiredAccountLevelResourceContainer
Expand Down Expand Up @@ -297,6 +346,144 @@ func (api *API) UploadWorker(ctx context.Context, rc *ResourceContainer, params
return r, nil
}

// GetWorkersScriptContent returns the pure script content of a worker.
//
// API reference: TODO: https://developers.cloudflare.com/api
func (api *API) GetWorkersScriptContent(ctx context.Context, rc *ResourceContainer, scriptName string) (string, error) {
if rc.Level != AccountRouteLevel {
return "", ErrRequiredAccountLevelResourceContainer
}

if rc.Identifier == "" {
return "", ErrMissingAccountID
}

uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s/content/v2", rc.Identifier, scriptName)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the API docs suggest this is just /accounts/:account_id/workers/scripts/:script/content. is that correct?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, technically both work, but /v2 is preferred for this GET endpoint so I'll update the API docs to match. Thanks for catching this!

res, err := api.makeRequestContextWithHeadersComplete(ctx, http.MethodGet, uri, nil, nil)
if err != nil {
return "", err
}

return string(res.Body), nil
}

// UpdateWorkersScriptContent pushes only script content, no metadata.
//
// API reference: TODO: https://developers.cloudflare.com/api
func (api *API) UpdateWorkersScriptContent(ctx context.Context, rc *ResourceContainer, params UpdateWorkersScriptContentParams) (WorkerScriptResponse, error) {
if rc.Level != AccountRouteLevel {
return WorkerScriptResponse{}, ErrRequiredAccountLevelResourceContainer
}

if rc.Identifier == "" {
return WorkerScriptResponse{}, ErrMissingAccountID
}

body := []byte(params.Script)
var (
contentType = "application/javascript"
err error
)

if params.Module {
var formattedParams CreateWorkerParams
formattedParams.Script = params.Script
formattedParams.ScriptName = params.ScriptName
formattedParams.Module = params.Module
formattedParams.DispatchNamespaceName = params.DispatchNamespaceName
contentType, body, err = formatMultipartBody(formattedParams)
if err != nil {
return WorkerScriptResponse{}, err
}
}

uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s/content", rc.Identifier, params.ScriptName)
if params.DispatchNamespaceName != nil {
uri = fmt.Sprintf("/accounts/%s/workers/dispatch_namespaces/%s/scripts/%s/content", rc.Identifier, *params.DispatchNamespaceName, params.ScriptName)
}

headers := make(http.Header)
headers.Set("Content-Type", contentType)
res, err := api.makeRequestContextWithHeaders(ctx, http.MethodPut, uri, body, headers)

var r WorkerScriptResponse
if err != nil {
return r, err
}

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

return r, nil
}

// GetWorkersScriptSettings returns the metadata of a worker.
//
// API reference: TODO: https://developers.cloudflare.com/api
func (api *API) GetWorkersScriptSettings(ctx context.Context, rc *ResourceContainer, scriptName string) (WorkerScriptSettingsResponse, error) {
if rc.Level != AccountRouteLevel {
return WorkerScriptSettingsResponse{}, ErrRequiredAccountLevelResourceContainer
}

if rc.Identifier == "" {
return WorkerScriptSettingsResponse{}, ErrMissingAccountID
}

uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s/settings", rc.Identifier, scriptName)
res, err := api.makeRequestContextWithHeaders(ctx, http.MethodGet, uri, nil, nil)
var r WorkerScriptSettingsResponse
if err != nil {
return r, err
}

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

r.Success = true

return r, nil
}

// UpdateWorkersScriptSettings pushes only script metadata.
//
// API reference: TODO: https://developers.cloudflare.com/api
func (api *API) UpdateWorkersScriptSettings(ctx context.Context, rc *ResourceContainer, params UpdateWorkersScriptSettingsParams) (WorkerScriptSettingsResponse, error) {
if rc.Level != AccountRouteLevel {
return WorkerScriptSettingsResponse{}, ErrRequiredAccountLevelResourceContainer
}

if rc.Identifier == "" {
return WorkerScriptSettingsResponse{}, ErrMissingAccountID
}

body, err := json.Marshal(params)
if err != nil {
return WorkerScriptSettingsResponse{}, err
}
headers := make(http.Header)
headers.Set("Content-Type", "application/json")

uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s/settings", rc.Identifier, params.ScriptName)
res, err := api.makeRequestContextWithHeaders(ctx, http.MethodPatch, uri, body, headers)
var r WorkerScriptSettingsResponse
if err != nil {
return r, err
}

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

r.Success = true

return r, nil
}

// Returns content-type, body, error.
func formatMultipartBody(params CreateWorkerParams) (string, []byte, error) {
var buf = &bytes.Buffer{}
Expand Down
4 changes: 2 additions & 2 deletions workers_account_settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ type WorkersAccountSettingsResponse struct {

// CreateWorkersAccountSettings sets the account settings for Workers.
//
// API reference: https://api.cloudflare.com/#worker-account-settings-create-worker-account-settings
// API reference: https://developers.cloudflare.com/api/operations/worker-account-settings-create-worker-account-settings
func (api *API) CreateWorkersAccountSettings(ctx context.Context, rc *ResourceContainer, params CreateWorkersAccountSettingsParameters) (WorkersAccountSettings, error) {
if rc.Identifier == "" {
return WorkersAccountSettings{}, ErrMissingAccountID
Expand All @@ -57,7 +57,7 @@ func (api *API) CreateWorkersAccountSettings(ctx context.Context, rc *ResourceCo

// WorkersAccountSettings returns the current account settings for Workers.
//
// API reference: https://api.cloudflare.com/#worker-account-settings-fetch-worker-account-settings
// API reference: https://developers.cloudflare.com/api/operations/worker-account-settings-fetch-worker-account-settings
func (api *API) WorkersAccountSettings(ctx context.Context, rc *ResourceContainer, params WorkersAccountSettingsParameters) (WorkersAccountSettings, error) {
if rc.Identifier == "" {
return WorkersAccountSettings{}, ErrMissingAccountID
Expand Down
4 changes: 2 additions & 2 deletions workers_cron_triggers.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ type UpdateWorkerCronTriggersParams struct {
// ListWorkerCronTriggers fetches all available cron triggers for a single Worker
// script.
//
// API reference: https://api.cloudflare.com/#worker-cron-trigger-get-cron-triggers
// API reference: https://developers.cloudflare.com/api/operations/worker-cron-trigger-get-cron-triggers
func (api *API) ListWorkerCronTriggers(ctx context.Context, rc *ResourceContainer, params ListWorkerCronTriggersParams) ([]WorkerCronTrigger, error) {
if rc.Level != AccountRouteLevel {
return []WorkerCronTrigger{}, ErrRequiredAccountLevelResourceContainer
Expand All @@ -65,7 +65,7 @@ func (api *API) ListWorkerCronTriggers(ctx context.Context, rc *ResourceContaine

// UpdateWorkerCronTriggers updates a single schedule for a Worker cron trigger.
//
// API reference: https://api.cloudflare.com/#worker-cron-trigger-update-cron-triggers
// API reference: https://developers.cloudflare.com/api/operations/worker-cron-trigger-update-cron-triggers
func (api *API) UpdateWorkerCronTriggers(ctx context.Context, rc *ResourceContainer, params UpdateWorkerCronTriggersParams) ([]WorkerCronTrigger, error) {
if rc.Level != AccountRouteLevel {
return []WorkerCronTrigger{}, ErrRequiredAccountLevelResourceContainer
Expand Down
8 changes: 4 additions & 4 deletions workers_domain.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ type WorkersDomainListResponse struct {

// ListWorkersDomains lists all Worker Domains.
//
// API reference: https://api.cloudflare.com/#worker-domain-list-domains
// API reference: https://developers.cloudflare.com/api/operations/worker-domain-list-domains
func (api *API) ListWorkersDomains(ctx context.Context, rc *ResourceContainer, params ListWorkersDomainParams) ([]WorkersDomain, error) {
if rc.Identifier == "" {
return []WorkersDomain{}, ErrMissingAccountID
Expand All @@ -74,7 +74,7 @@ func (api *API) ListWorkersDomains(ctx context.Context, rc *ResourceContainer, p

// AttachWorkersDomain attaches a worker to a zone and hostname.
//
// API reference: https://api.cloudflare.com/#worker-domain-attach-to-domain
// API reference: https://developers.cloudflare.com/api/operations/worker-domain-attach-to-domain
func (api *API) AttachWorkersDomain(ctx context.Context, rc *ResourceContainer, domain AttachWorkersDomainParams) (WorkersDomain, error) {
if rc.Identifier == "" {
return WorkersDomain{}, ErrMissingAccountID
Expand Down Expand Up @@ -112,7 +112,7 @@ func (api *API) AttachWorkersDomain(ctx context.Context, rc *ResourceContainer,

// GetWorkersDomain gets a single Worker Domain.
//
// API reference: https://api.cloudflare.com/#worker-domain-get-a-domain
// API reference: https://developers.cloudflare.com/api/operations/worker-domain-get-a-domain
func (api *API) GetWorkersDomain(ctx context.Context, rc *ResourceContainer, domainID string) (WorkersDomain, error) {
if rc.Identifier == "" {
return WorkersDomain{}, ErrMissingAccountID
Expand All @@ -134,7 +134,7 @@ func (api *API) GetWorkersDomain(ctx context.Context, rc *ResourceContainer, dom

// DetachWorkersDomain detaches a worker from a zone and hostname.
//
// API reference: https://api.cloudflare.com/#worker-domain-detach-from-domain
// API reference: https://developers.cloudflare.com/api/operations/worker-domain-detach-from-domain
func (api *API) DetachWorkersDomain(ctx context.Context, rc *ResourceContainer, domainID string) error {
if rc.Identifier == "" {
return ErrMissingAccountID
Expand Down