lego/vendor/github.com/cloudflare/cloudflare-go/workers.go
2019-07-04 18:24:33 +02:00

312 lines
11 KiB
Go

package cloudflare
import (
"encoding/json"
"net/http"
"time"
"github.com/pkg/errors"
)
// WorkerRequestParams provides parameters for worker requests for both enterprise and standard requests
type WorkerRequestParams struct {
ZoneID string
ScriptName string
}
// WorkerRoute aka filters are patterns used to enable or disable workers that match requests.
//
// API reference: https://api.cloudflare.com/#worker-filters-properties
type WorkerRoute struct {
ID string `json:"id,omitempty"`
Pattern string `json:"pattern"`
Enabled bool `json:"enabled"`
Script string `json:"script,omitempty"`
}
// WorkerRoutesResponse embeds Response struct and slice of WorkerRoutes
type WorkerRoutesResponse struct {
Response
Routes []WorkerRoute `json:"result"`
}
// WorkerRouteResponse embeds Response struct and a single WorkerRoute
type WorkerRouteResponse struct {
Response
WorkerRoute `json:"result"`
}
// WorkerScript Cloudflare Worker struct with metadata
type WorkerScript struct {
WorkerMetaData
Script string `json:"script"`
}
// WorkerMetaData contains worker script information such as size, creation & modification dates
type WorkerMetaData struct {
ID string `json:"id,omitempty"`
ETAG string `json:"etag,omitempty"`
Size int `json:"size,omitempty"`
CreatedOn time.Time `json:"created_on,omitempty"`
ModifiedOn time.Time `json:"modified_on,omitempty"`
}
// WorkerListResponse wrapper struct for API response to worker script list API call
type WorkerListResponse struct {
Response
WorkerList []WorkerMetaData `json:"result"`
}
// WorkerScriptResponse wrapper struct for API response to worker script calls
type WorkerScriptResponse struct {
Response
WorkerScript `json:"result"`
}
// DeleteWorker deletes worker for a zone.
//
// API reference: https://api.cloudflare.com/#worker-script-delete-worker
func (api *API) DeleteWorker(requestParams *WorkerRequestParams) (WorkerScriptResponse, error) {
// if ScriptName is provided we will treat as org request
if requestParams.ScriptName != "" {
return api.deleteWorkerWithName(requestParams.ScriptName)
}
uri := "/zones/" + requestParams.ZoneID + "/workers/script"
res, err := api.makeRequest("DELETE", uri, nil)
var r WorkerScriptResponse
if err != nil {
return r, errors.Wrap(err, errMakeRequestError)
}
err = json.Unmarshal(res, &r)
if err != nil {
return r, errors.Wrap(err, errUnmarshalError)
}
return r, nil
}
// DeleteWorkerWithName deletes worker for a zone.
// This is an enterprise only feature https://developers.cloudflare.com/workers/api/config-api-for-enterprise
// organizationID must be specified as api option https://godoc.org/github.com/cloudflare/cloudflare-go#UsingOrganization
//
// API reference: https://api.cloudflare.com/#worker-script-delete-worker
func (api *API) deleteWorkerWithName(scriptName string) (WorkerScriptResponse, error) {
if api.OrganizationID == "" {
return WorkerScriptResponse{}, errors.New("organization ID required for enterprise only request")
}
uri := "/accounts/" + api.OrganizationID + "/workers/scripts/" + scriptName
res, err := api.makeRequest("DELETE", uri, nil)
var r WorkerScriptResponse
if err != nil {
return r, errors.Wrap(err, errMakeRequestError)
}
err = json.Unmarshal(res, &r)
if err != nil {
return r, errors.Wrap(err, errUnmarshalError)
}
return r, nil
}
// DownloadWorker fetch raw script content for your worker returns []byte containing worker code js
//
// API reference: https://api.cloudflare.com/#worker-script-download-worker
func (api *API) DownloadWorker(requestParams *WorkerRequestParams) (WorkerScriptResponse, error) {
if requestParams.ScriptName != "" {
return api.downloadWorkerWithName(requestParams.ScriptName)
}
uri := "/zones/" + requestParams.ZoneID + "/workers/script"
res, err := api.makeRequest("GET", uri, nil)
var r WorkerScriptResponse
if err != nil {
return r, errors.Wrap(err, errMakeRequestError)
}
r.Script = string(res)
r.Success = true
return r, nil
}
// DownloadWorkerWithName fetch raw script content for your worker returns string containing worker code js
// This is an enterprise only feature https://developers.cloudflare.com/workers/api/config-api-for-enterprise/
//
// API reference: https://api.cloudflare.com/#worker-script-download-worker
func (api *API) downloadWorkerWithName(scriptName string) (WorkerScriptResponse, error) {
if api.OrganizationID == "" {
return WorkerScriptResponse{}, errors.New("organization ID required for enterprise only request")
}
uri := "/accounts/" + api.OrganizationID + "/workers/scripts/" + scriptName
res, err := api.makeRequest("GET", uri, nil)
var r WorkerScriptResponse
if err != nil {
return r, errors.Wrap(err, errMakeRequestError)
}
r.Script = string(res)
r.Success = true
return r, nil
}
// ListWorkerScripts returns list of worker scripts for given organization
// This is an enterprise only feature https://developers.cloudflare.com/workers/api/config-api-for-enterprise
//
// API reference: https://developers.cloudflare.com/workers/api/config-api-for-enterprise/
func (api *API) ListWorkerScripts() (WorkerListResponse, error) {
if api.OrganizationID == "" {
return WorkerListResponse{}, errors.New("organization ID required for enterprise only request")
}
uri := "/accounts/" + api.OrganizationID + "/workers/scripts"
res, err := api.makeRequest("GET", uri, nil)
if err != nil {
return WorkerListResponse{}, errors.Wrap(err, errMakeRequestError)
}
var r WorkerListResponse
err = json.Unmarshal(res, &r)
if err != nil {
return WorkerListResponse{}, errors.Wrap(err, errUnmarshalError)
}
return r, nil
}
// UploadWorker push raw script content for your worker
//
// API reference: https://api.cloudflare.com/#worker-script-upload-worker
func (api *API) UploadWorker(requestParams *WorkerRequestParams, data string) (WorkerScriptResponse, error) {
if requestParams.ScriptName != "" {
return api.uploadWorkerWithName(requestParams.ScriptName, data)
}
uri := "/zones/" + requestParams.ZoneID + "/workers/script"
headers := make(http.Header)
headers.Set("Content-Type", "application/javascript")
res, err := api.makeRequestWithHeaders("PUT", uri, []byte(data), headers)
var r WorkerScriptResponse
if err != nil {
return r, errors.Wrap(err, errMakeRequestError)
}
err = json.Unmarshal(res, &r)
if err != nil {
return r, errors.Wrap(err, errUnmarshalError)
}
return r, nil
}
// UploadWorkerWithName push raw script content for your worker
// This is an enterprise only feature https://developers.cloudflare.com/workers/api/config-api-for-enterprise/
//
// API reference: https://api.cloudflare.com/#worker-script-upload-worker
func (api *API) uploadWorkerWithName(scriptName string, data string) (WorkerScriptResponse, error) {
if api.OrganizationID == "" {
return WorkerScriptResponse{}, errors.New("organization ID required for enterprise only request")
}
uri := "/accounts/" + api.OrganizationID + "/workers/scripts/" + scriptName
headers := make(http.Header)
headers.Set("Content-Type", "application/javascript")
res, err := api.makeRequestWithHeaders("PUT", uri, []byte(data), headers)
var r WorkerScriptResponse
if err != nil {
return r, errors.Wrap(err, errMakeRequestError)
}
err = json.Unmarshal(res, &r)
if err != nil {
return r, errors.Wrap(err, errUnmarshalError)
}
return r, nil
}
// CreateWorkerRoute creates worker route for a zone
//
// API reference: https://api.cloudflare.com/#worker-filters-create-filter
func (api *API) CreateWorkerRoute(zoneID string, route WorkerRoute) (WorkerRouteResponse, error) {
// Check whether a script name is defined in order to determine whether
// to use the single-script or multi-script endpoint.
pathComponent := "filters"
if route.Script != "" {
if api.OrganizationID == "" {
return WorkerRouteResponse{}, errors.New("organization ID required for enterprise only request")
}
pathComponent = "routes"
}
uri := "/zones/" + zoneID + "/workers/" + pathComponent
res, err := api.makeRequest("POST", uri, route)
if err != nil {
return WorkerRouteResponse{}, errors.Wrap(err, errMakeRequestError)
}
var r WorkerRouteResponse
err = json.Unmarshal(res, &r)
if err != nil {
return WorkerRouteResponse{}, errors.Wrap(err, errUnmarshalError)
}
return r, nil
}
// DeleteWorkerRoute deletes worker route for a zone
//
// API reference: https://api.cloudflare.com/#worker-filters-delete-filter
func (api *API) DeleteWorkerRoute(zoneID string, routeID string) (WorkerRouteResponse, error) {
// For deleting a route, it doesn't matter whether we use the
// single-script or multi-script endpoint
uri := "/zones/" + zoneID + "/workers/filters/" + routeID
res, err := api.makeRequest("DELETE", uri, nil)
if err != nil {
return WorkerRouteResponse{}, errors.Wrap(err, errMakeRequestError)
}
var r WorkerRouteResponse
err = json.Unmarshal(res, &r)
if err != nil {
return WorkerRouteResponse{}, errors.Wrap(err, errUnmarshalError)
}
return r, nil
}
// ListWorkerRoutes returns list of worker routes
//
// API reference: https://api.cloudflare.com/#worker-filters-list-filters
func (api *API) ListWorkerRoutes(zoneID string) (WorkerRoutesResponse, error) {
pathComponent := "filters"
if api.OrganizationID != "" {
pathComponent = "routes"
}
uri := "/zones/" + zoneID + "/workers/" + pathComponent
res, err := api.makeRequest("GET", uri, nil)
if err != nil {
return WorkerRoutesResponse{}, errors.Wrap(err, errMakeRequestError)
}
var r WorkerRoutesResponse
err = json.Unmarshal(res, &r)
if err != nil {
return WorkerRoutesResponse{}, errors.Wrap(err, errUnmarshalError)
}
for i := range r.Routes {
route := &r.Routes[i]
// The Enabled flag will not be set in the multi-script API response
// so we manually set it to true if the script name is not empty
// in case any multi-script customers rely on the Enabled field
if route.Script != "" {
route.Enabled = true
}
}
return r, nil
}
// UpdateWorkerRoute updates worker route for a zone.
//
// API reference: https://api.cloudflare.com/#worker-filters-update-filter
func (api *API) UpdateWorkerRoute(zoneID string, routeID string, route WorkerRoute) (WorkerRouteResponse, error) {
// Check whether a script name is defined in order to determine whether
// to use the single-script or multi-script endpoint.
pathComponent := "filters"
if route.Script != "" {
if api.OrganizationID == "" {
return WorkerRouteResponse{}, errors.New("organization ID required for enterprise only request")
}
pathComponent = "routes"
}
uri := "/zones/" + zoneID + "/workers/" + pathComponent + "/" + routeID
res, err := api.makeRequest("PUT", uri, route)
if err != nil {
return WorkerRouteResponse{}, errors.Wrap(err, errMakeRequestError)
}
var r WorkerRouteResponse
err = json.Unmarshal(res, &r)
if err != nil {
return WorkerRouteResponse{}, errors.Wrap(err, errUnmarshalError)
}
return r, nil
}