github.com/akamai/AkamaiOPEN-edgegrid-golang/v2@v2.17.0/pkg/appsec/rate_policy.go (about)

     1  package appsec
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"fmt"
     7  	"net/http"
     8  
     9  	validation "github.com/go-ozzo/ozzo-validation/v4"
    10  )
    11  
    12  type (
    13  	// The RatePolicy interface supports creating, retrieving, updating and removing rate policies.
    14  	//
    15  	// https://developer.akamai.com/api/cloud_security/application_security/v1.html#ratepolicy
    16  	RatePolicy interface {
    17  		// https://developer.akamai.com/api/cloud_security/application_security/v1.html#getratepolicies
    18  		GetRatePolicies(ctx context.Context, params GetRatePoliciesRequest) (*GetRatePoliciesResponse, error)
    19  
    20  		// https://developer.akamai.com/api/cloud_security/application_security/v1.html#getratepolicy
    21  		GetRatePolicy(ctx context.Context, params GetRatePolicyRequest) (*GetRatePolicyResponse, error)
    22  
    23  		// https://developer.akamai.com/api/cloud_security/application_security/v1.html#postratepolicies
    24  		CreateRatePolicy(ctx context.Context, params CreateRatePolicyRequest) (*CreateRatePolicyResponse, error)
    25  
    26  		// https://developer.akamai.com/api/cloud_security/application_security/v1.html#putratepolicy
    27  		UpdateRatePolicy(ctx context.Context, params UpdateRatePolicyRequest) (*UpdateRatePolicyResponse, error)
    28  
    29  		// https://developer.akamai.com/api/cloud_security/application_security/v1.html#deleteratepolicy
    30  		RemoveRatePolicy(ctx context.Context, params RemoveRatePolicyRequest) (*RemoveRatePolicyResponse, error)
    31  	}
    32  
    33  	// CreateRatePolicyRequest is used to create a rate policy.
    34  	CreateRatePolicyRequest struct {
    35  		ID             int             `json:"-"`
    36  		ConfigID       int             `json:"configId"`
    37  		ConfigVersion  int             `json:"configVersion"`
    38  		JsonPayloadRaw json.RawMessage `json:"-"`
    39  	}
    40  
    41  	// CreateRatePolicyResponse is returned from a call to CreateRatePolicy.
    42  	CreateRatePolicyResponse struct {
    43  		ID                    int    `json:"id"`
    44  		ConfigID              int    `json:"configId"`
    45  		ConfigVersion         int    `json:"configVersion"`
    46  		MatchType             string `json:"matchType"`
    47  		Type                  string `json:"type"`
    48  		Name                  string `json:"name"`
    49  		Description           string `json:"description"`
    50  		AverageThreshold      int    `json:"averageThreshold"`
    51  		BurstThreshold        int    `json:"burstThreshold"`
    52  		ClientIdentifier      string `json:"clientIdentifier"`
    53  		UseXForwardForHeaders bool   `json:"useXForwardForHeaders"`
    54  		RequestType           string `json:"requestType"`
    55  		SameActionOnIpv6      bool   `json:"sameActionOnIpv6"`
    56  		Path                  struct {
    57  			PositiveMatch bool     `json:"positiveMatch"`
    58  			Values        []string `json:"values"`
    59  		} `json:"path"`
    60  		PathMatchType        string `json:"pathMatchType"`
    61  		PathURIPositiveMatch bool   `json:"pathUriPositiveMatch"`
    62  		FileExtensions       struct {
    63  			PositiveMatch bool     `json:"positiveMatch"`
    64  			Values        []string `json:"values"`
    65  		} `json:"fileExtensions"`
    66  		Hosts                  *RatePoliciesHosts      `json:"hosts,omitempty"`
    67  		Hostnames              []string                `json:"hostnames"`
    68  		AdditionalMatchOptions []RatePolicyMatchOption `json:"additionalMatchOptions,omitempty"`
    69  		QueryParameters        []struct {
    70  			Name          string   `json:"name"`
    71  			Values        []string `json:"values"`
    72  			PositiveMatch bool     `json:"positiveMatch"`
    73  			ValueInRange  bool     `json:"valueInRange"`
    74  		} `json:"queryParameters"`
    75  		CreateDate string          `json:"-"`
    76  		UpdateDate string          `json:"-"`
    77  		Used       json.RawMessage `json:"used"`
    78  	}
    79  
    80  	// UpdateRatePolicyRequest is used to modify an existing rate policy.
    81  	UpdateRatePolicyRequest struct {
    82  		RatePolicyID   int             `json:"id"`
    83  		ConfigID       int             `json:"configId"`
    84  		ConfigVersion  int             `json:"configVersion"`
    85  		JsonPayloadRaw json.RawMessage `json:"-"`
    86  	}
    87  
    88  	// UpdateRatePolicyResponse is returned from a call to UpdateRatePolicy.
    89  	UpdateRatePolicyResponse struct {
    90  		ID                    int    `json:"id"`
    91  		ConfigID              int    `json:"configId"`
    92  		ConfigVersion         int    `json:"configVersion"`
    93  		MatchType             string `json:"matchType"`
    94  		Type                  string `json:"type"`
    95  		Name                  string `json:"name"`
    96  		Description           string `json:"description"`
    97  		AverageThreshold      int    `json:"averageThreshold"`
    98  		BurstThreshold        int    `json:"burstThreshold"`
    99  		ClientIdentifier      string `json:"clientIdentifier"`
   100  		UseXForwardForHeaders bool   `json:"useXForwardForHeaders"`
   101  		RequestType           string `json:"requestType"`
   102  		SameActionOnIpv6      bool   `json:"sameActionOnIpv6"`
   103  		Path                  struct {
   104  			PositiveMatch bool     `json:"positiveMatch"`
   105  			Values        []string `json:"values"`
   106  		} `json:"path"`
   107  		PathMatchType        string `json:"pathMatchType"`
   108  		PathURIPositiveMatch bool   `json:"pathUriPositiveMatch"`
   109  		FileExtensions       struct {
   110  			PositiveMatch bool     `json:"positiveMatch"`
   111  			Values        []string `json:"values"`
   112  		} `json:"fileExtensions"`
   113  		Hosts                  *RatePoliciesHosts      `json:"hosts,omitempty"`
   114  		Hostnames              []string                `json:"hostnames"`
   115  		AdditionalMatchOptions []RatePolicyMatchOption `json:"additionalMatchOptions,omitempty"`
   116  		QueryParameters        []struct {
   117  			Name          string   `json:"name"`
   118  			Values        []string `json:"values"`
   119  			PositiveMatch bool     `json:"positiveMatch"`
   120  			ValueInRange  bool     `json:"valueInRange"`
   121  		} `json:"queryParameters"`
   122  		CreateDate string          `json:"-"`
   123  		UpdateDate string          `json:"-"`
   124  		Used       json.RawMessage `json:"used"`
   125  	}
   126  
   127  	// RemoveRatePolicyRequest is used to remove a rate policy.
   128  	RemoveRatePolicyRequest struct {
   129  		ConfigID      int `json:"configId"`
   130  		ConfigVersion int `json:"configVersion"`
   131  		RatePolicyID  int `json:"ratePolicyId"`
   132  	}
   133  
   134  	// RemoveRatePolicyResponse is returned from a call to RemoveRatePolicy.
   135  	RemoveRatePolicyResponse struct {
   136  		ID                    int    `json:"id"`
   137  		ConfigID              int    `json:"configId"`
   138  		ConfigVersion         int    `json:"configVersion"`
   139  		MatchType             string `json:"matchType"`
   140  		Type                  string `json:"type"`
   141  		Name                  string `json:"name"`
   142  		Description           string `json:"description"`
   143  		AverageThreshold      int    `json:"averageThreshold"`
   144  		BurstThreshold        int    `json:"burstThreshold"`
   145  		ClientIdentifier      string `json:"clientIdentifier"`
   146  		UseXForwardForHeaders bool   `json:"useXForwardForHeaders"`
   147  		RequestType           string `json:"requestType"`
   148  		SameActionOnIpv6      bool   `json:"sameActionOnIpv6"`
   149  		Path                  struct {
   150  			PositiveMatch bool     `json:"positiveMatch"`
   151  			Values        []string `json:"values"`
   152  		} `json:"path"`
   153  		PathMatchType        string `json:"pathMatchType"`
   154  		PathURIPositiveMatch bool   `json:"pathUriPositiveMatch"`
   155  		FileExtensions       struct {
   156  			PositiveMatch bool     `json:"positiveMatch"`
   157  			Values        []string `json:"values"`
   158  		} `json:"fileExtensions"`
   159  		Hosts                  *RatePoliciesHosts      `json:"hosts,omitempty"`
   160  		Hostnames              []string                `json:"hostnames"`
   161  		AdditionalMatchOptions []RatePolicyMatchOption `json:"additionalMatchOptions,omitempty"`
   162  		QueryParameters        []struct {
   163  			Name          string   `json:"name"`
   164  			Values        []string `json:"values"`
   165  			PositiveMatch bool     `json:"positiveMatch"`
   166  			ValueInRange  bool     `json:"valueInRange"`
   167  		} `json:"queryParameters"`
   168  		CreateDate string          `json:"-"`
   169  		UpdateDate string          `json:"-"`
   170  		Used       json.RawMessage `json:"used"`
   171  	}
   172  
   173  	// GetRatePoliciesRequest is used to retrieve the rate policies for a configuration.
   174  	GetRatePoliciesRequest struct {
   175  		ConfigID      int `json:"configId"`
   176  		ConfigVersion int `json:"configVersion"`
   177  		RatePolicyID  int `json:"ratePolicyId"`
   178  	}
   179  
   180  	// GetRatePoliciesResponse is returned from a call to GetRatePolicies.
   181  	GetRatePoliciesResponse struct {
   182  		RatePolicies []struct {
   183  			ID                     int                        `json:"id"`
   184  			ConfigID               int                        `json:"-"`
   185  			ConfigVersion          int                        `json:"-"`
   186  			MatchType              string                     `json:"matchType,omitempty"`
   187  			Type                   string                     `json:"type,omitempty"`
   188  			Name                   string                     `json:"name,omitempty"`
   189  			Description            string                     `json:"description,omitempty"`
   190  			AverageThreshold       int                        `json:"averageThreshold,omitempty"`
   191  			BurstThreshold         int                        `json:"burstThreshold,omitempty"`
   192  			ClientIdentifier       string                     `json:"clientIdentifier,omitempty"`
   193  			UseXForwardForHeaders  bool                       `json:"useXForwardForHeaders"`
   194  			RequestType            string                     `json:"requestType,omitempty"`
   195  			SameActionOnIpv6       bool                       `json:"sameActionOnIpv6"`
   196  			Path                   *RatePolicyPath            `json:"path,omitempty"`
   197  			PathMatchType          string                     `json:"pathMatchType,omitempty"`
   198  			PathURIPositiveMatch   bool                       `json:"pathUriPositiveMatch"`
   199  			FileExtensions         *RatePolicyFileExtensions  `json:"fileExtensions,omitempty"`
   200  			Hosts                  *RatePoliciesHosts         `json:"hosts,omitempty"`
   201  			Hostnames              []string                   `json:"hostnames,omitempty"`
   202  			AdditionalMatchOptions []RatePolicyMatchOption    `json:"additionalMatchOptions,omitempty"`
   203  			QueryParameters        *RatePolicyQueryParameters `json:"queryParameters,omitempty"`
   204  			CreateDate             string                     `json:"-"`
   205  			UpdateDate             string                     `json:"-"`
   206  			Used                   json.RawMessage            `json:"used"`
   207  			SameActionOnIpv        bool                       `json:"sameActionOnIpv"`
   208  			APISelectors           *RatePolicyAPISelectors    `json:"apiSelectors,omitempty"`
   209  			BodyParameters         *RatePolicyBodyParameters  `json:"bodyParameters,omitempty"`
   210  		} `json:"ratePolicies,omitempty"`
   211  	}
   212  
   213  	// GetRatePolicyRequest is used to retrieve information about a specific rate policy.
   214  	GetRatePolicyRequest struct {
   215  		ConfigID      int `json:"configId"`
   216  		ConfigVersion int `json:"configVersion"`
   217  		RatePolicyID  int `json:"ratePolicyId"`
   218  	}
   219  
   220  	// GetRatePolicyResponse is returned from a call to GetRatePolicy.
   221  	GetRatePolicyResponse struct {
   222  		ID                     int                        `json:"-"`
   223  		ConfigID               int                        `json:"-"`
   224  		ConfigVersion          int                        `json:"-"`
   225  		MatchType              string                     `json:"matchType,omitempty"`
   226  		Type                   string                     `json:"type,omitempty"`
   227  		Name                   string                     `json:"name,omitempty"`
   228  		Description            string                     `json:"description,omitempty"`
   229  		AverageThreshold       int                        `json:"averageThreshold,omitempty"`
   230  		BurstThreshold         int                        `json:"burstThreshold,omitempty"`
   231  		ClientIdentifier       string                     `json:"clientIdentifier,omitempty"`
   232  		UseXForwardForHeaders  bool                       `json:"useXForwardForHeaders"`
   233  		RequestType            string                     `json:"requestType,omitempty"`
   234  		SameActionOnIpv6       bool                       `json:"sameActionOnIpv6"`
   235  		Path                   *RatePolicyPath            `json:"path,omitempty"`
   236  		PathMatchType          string                     `json:"pathMatchType,omitempty"`
   237  		PathURIPositiveMatch   bool                       `json:"pathUriPositiveMatch"`
   238  		FileExtensions         *RatePolicyFileExtensions  `json:"fileExtensions,omitempty"`
   239  		Hosts                  *RatePoliciesHosts         `json:"hosts,omitempty"`
   240  		Hostnames              []string                   `json:"hostnames,omitempty"`
   241  		AdditionalMatchOptions []RatePolicyMatchOption    `json:"additionalMatchOptions,omitempty"`
   242  		QueryParameters        *RatePolicyQueryParameters `json:"queryParameters,omitempty"`
   243  		CreateDate             string                     `json:"-"`
   244  		UpdateDate             string                     `json:"-"`
   245  		Used                   bool                       `json:"-"`
   246  	}
   247  
   248  	// RatePolicyAPISelectors is used as part of a rate policy description.
   249  	RatePolicyAPISelectors []struct {
   250  		APIDefinitionID    int   `json:"apiDefinitionId,omitempty"`
   251  		DefinedResources   *bool `json:"definedResources,omitempty"`
   252  		ResourceIds        []int `json:"resourceIds"`
   253  		UndefinedResources *bool `json:"undefinedResources,omitempty"`
   254  	}
   255  
   256  	// RatePolicyBodyParameters is used as part of a rate policy description.
   257  	RatePolicyBodyParameters []struct {
   258  		Name          string   `json:"name,omitempty"`
   259  		Values        []string `json:"values,omitempty"`
   260  		PositiveMatch bool     `json:"positiveMatch"`
   261  		ValueInRange  bool     `json:"valueInRange"`
   262  	}
   263  
   264  	// RatePolicyPath is used as part of a rate policy description.
   265  	RatePolicyPath struct {
   266  		PositiveMatch bool     `json:"positiveMatch"`
   267  		Values        []string `json:"values,omitempty"`
   268  	}
   269  
   270  	// RatePolicyFileExtensions is used as part of a rate policy description.
   271  	RatePolicyFileExtensions struct {
   272  		PositiveMatch bool     `json:"positiveMatch"`
   273  		Values        []string `json:"values,omitempty"`
   274  	}
   275  
   276  	// RatePolicyMatchOption is used as part of a rate policy description.
   277  	RatePolicyMatchOption struct {
   278  		PositiveMatch bool     `json:"positiveMatch"`
   279  		Type          string   `json:"type,omitempty"`
   280  		Values        []string `json:"values,omitempty"`
   281  	}
   282  
   283  	// RatePolicyQueryParameters is used as part of a rate policy description.
   284  	RatePolicyQueryParameters []struct {
   285  		Name          string   `json:"name,omitempty"`
   286  		Values        []string `json:"values,omitempty"`
   287  		PositiveMatch bool     `json:"positiveMatch"`
   288  		ValueInRange  bool     `json:"valueInRange"`
   289  	}
   290  
   291  	// RatePoliciesHosts is used as part of a rate policy description.
   292  	RatePoliciesHosts struct {
   293  		Values        *[]string        `json:"values,omitempty"`
   294  		PositiveMatch *json.RawMessage `json:"positiveMatch,omitempty"`
   295  	}
   296  )
   297  
   298  // Validate validates a GetRatePolicyRequest.
   299  func (v GetRatePolicyRequest) Validate() error {
   300  	return validation.Errors{
   301  		"ConfigID":      validation.Validate(v.ConfigID, validation.Required),
   302  		"ConfigVersion": validation.Validate(v.ConfigVersion, validation.Required),
   303  		"RatePolicyID":  validation.Validate(v.RatePolicyID, validation.Required),
   304  	}.Filter()
   305  }
   306  
   307  // Validate validates a GetRatePolicysRequest.
   308  func (v GetRatePoliciesRequest) Validate() error {
   309  	return validation.Errors{
   310  		"ConfigID":      validation.Validate(v.ConfigID, validation.Required),
   311  		"ConfigVersion": validation.Validate(v.ConfigVersion, validation.Required),
   312  	}.Filter()
   313  }
   314  
   315  // Validate validates a CreateRatePolicyRequest.
   316  func (v CreateRatePolicyRequest) Validate() error {
   317  	return validation.Errors{
   318  		"ConfigID":      validation.Validate(v.ConfigID, validation.Required),
   319  		"ConfigVersion": validation.Validate(v.ConfigVersion, validation.Required),
   320  	}.Filter()
   321  }
   322  
   323  // Validate validates an UpdateRatePolicyRequest.
   324  func (v UpdateRatePolicyRequest) Validate() error {
   325  	return validation.Errors{
   326  		"ConfigID":      validation.Validate(v.ConfigID, validation.Required),
   327  		"ConfigVersion": validation.Validate(v.ConfigVersion, validation.Required),
   328  		"RatePolicyID":  validation.Validate(v.RatePolicyID, validation.Required),
   329  	}.Filter()
   330  }
   331  
   332  // Validate validates a RemoveRatePolicyRequest.
   333  func (v RemoveRatePolicyRequest) Validate() error {
   334  	return validation.Errors{
   335  		"ConfigID":      validation.Validate(v.ConfigID, validation.Required),
   336  		"ConfigVersion": validation.Validate(v.ConfigVersion, validation.Required),
   337  		"RatePolicyID":  validation.Validate(v.RatePolicyID, validation.Required),
   338  	}.Filter()
   339  }
   340  
   341  func (p *appsec) GetRatePolicy(ctx context.Context, params GetRatePolicyRequest) (*GetRatePolicyResponse, error) {
   342  	logger := p.Log(ctx)
   343  	logger.Debug("GetRatePolicy")
   344  
   345  	if err := params.Validate(); err != nil {
   346  		return nil, fmt.Errorf("%w: %s", ErrStructValidation, err.Error())
   347  	}
   348  
   349  	uri := fmt.Sprintf(
   350  		"/appsec/v1/configs/%d/versions/%d/rate-policies/%d",
   351  		params.ConfigID,
   352  		params.ConfigVersion,
   353  		params.RatePolicyID)
   354  
   355  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri, nil)
   356  	if err != nil {
   357  		return nil, fmt.Errorf("failed to create GetRatePolicy request: %w", err)
   358  	}
   359  
   360  	var result GetRatePolicyResponse
   361  	resp, err := p.Exec(req, &result)
   362  	if err != nil {
   363  		return nil, fmt.Errorf("get rate policy request failed: %w", err)
   364  	}
   365  	if resp.StatusCode != http.StatusOK {
   366  		return nil, p.Error(resp)
   367  	}
   368  
   369  	return &result, nil
   370  }
   371  
   372  func (p *appsec) GetRatePolicies(ctx context.Context, params GetRatePoliciesRequest) (*GetRatePoliciesResponse, error) {
   373  	logger := p.Log(ctx)
   374  	logger.Debug("GetRatePolicies")
   375  
   376  	if err := params.Validate(); err != nil {
   377  		return nil, fmt.Errorf("%w: %s", ErrStructValidation, err.Error())
   378  	}
   379  
   380  	uri := fmt.Sprintf(
   381  		"/appsec/v1/configs/%d/versions/%d/rate-policies",
   382  		params.ConfigID,
   383  		params.ConfigVersion,
   384  	)
   385  
   386  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri, nil)
   387  	if err != nil {
   388  		return nil, fmt.Errorf("failed to create GetRatePolicies request: %w", err)
   389  	}
   390  
   391  	var result GetRatePoliciesResponse
   392  	resp, err := p.Exec(req, &result)
   393  	if err != nil {
   394  		return nil, fmt.Errorf("get rate policies request failed: %w", err)
   395  	}
   396  	if resp.StatusCode != http.StatusOK {
   397  		return nil, p.Error(resp)
   398  	}
   399  
   400  	if params.RatePolicyID != 0 {
   401  		var filteredResult GetRatePoliciesResponse
   402  		for _, val := range result.RatePolicies {
   403  			if val.ID == params.RatePolicyID {
   404  				filteredResult.RatePolicies = append(filteredResult.RatePolicies, val)
   405  			}
   406  		}
   407  		return &filteredResult, nil
   408  	}
   409  
   410  	return &result, nil
   411  }
   412  
   413  func (p *appsec) UpdateRatePolicy(ctx context.Context, params UpdateRatePolicyRequest) (*UpdateRatePolicyResponse, error) {
   414  	logger := p.Log(ctx)
   415  	logger.Debug("UpdateRatePolicy")
   416  
   417  	if err := params.Validate(); err != nil {
   418  		return nil, fmt.Errorf("%w: %s", ErrStructValidation, err.Error())
   419  	}
   420  
   421  	uri := fmt.Sprintf(
   422  		"/appsec/v1/configs/%d/versions/%d/rate-policies/%d",
   423  		params.ConfigID,
   424  		params.ConfigVersion,
   425  		params.RatePolicyID,
   426  	)
   427  
   428  	req, err := http.NewRequestWithContext(ctx, http.MethodPut, uri, nil)
   429  	if err != nil {
   430  		return nil, fmt.Errorf("failed to create UpdateRatePolicy request: %w", err)
   431  	}
   432  
   433  	var result UpdateRatePolicyResponse
   434  	req.Header.Set("Content-Type", "application/json")
   435  	resp, err := p.Exec(req, &result, params.JsonPayloadRaw)
   436  	if err != nil {
   437  		return nil, fmt.Errorf("update rate policy request failed: %w", err)
   438  	}
   439  	if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated {
   440  		return nil, p.Error(resp)
   441  	}
   442  
   443  	return &result, nil
   444  }
   445  
   446  func (p *appsec) CreateRatePolicy(ctx context.Context, params CreateRatePolicyRequest) (*CreateRatePolicyResponse, error) {
   447  	logger := p.Log(ctx)
   448  	logger.Debug("CreateRatePolicy")
   449  
   450  	if err := params.Validate(); err != nil {
   451  		return nil, fmt.Errorf("%w: %s", ErrStructValidation, err.Error())
   452  	}
   453  
   454  	uri := fmt.Sprintf(
   455  		"/appsec/v1/configs/%d/versions/%d/rate-policies",
   456  		params.ConfigID,
   457  		params.ConfigVersion,
   458  	)
   459  
   460  	req, err := http.NewRequestWithContext(ctx, http.MethodPost, uri, nil)
   461  	if err != nil {
   462  		return nil, fmt.Errorf("failed to create CreateRatePolicy request: %w", err)
   463  	}
   464  
   465  	var result CreateRatePolicyResponse
   466  	req.Header.Set("Content-Type", "application/json")
   467  	resp, err := p.Exec(req, &result, params.JsonPayloadRaw)
   468  	if err != nil {
   469  		return nil, fmt.Errorf("create rate policy request failed: %w", err)
   470  	}
   471  	if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated {
   472  		return nil, p.Error(resp)
   473  	}
   474  
   475  	return &result, nil
   476  }
   477  
   478  func (p *appsec) RemoveRatePolicy(ctx context.Context, params RemoveRatePolicyRequest) (*RemoveRatePolicyResponse, error) {
   479  	logger := p.Log(ctx)
   480  	logger.Debug("RemoveRatePolicy")
   481  
   482  	if err := params.Validate(); err != nil {
   483  		return nil, fmt.Errorf("%w: %s", ErrStructValidation, err.Error())
   484  	}
   485  
   486  	uri := fmt.Sprintf("/appsec/v1/configs/%d/versions/%d/rate-policies/%d", params.ConfigID, params.ConfigVersion, params.RatePolicyID)
   487  	req, err := http.NewRequestWithContext(ctx, http.MethodDelete, uri, nil)
   488  	if err != nil {
   489  		return nil, fmt.Errorf("failed to create RemoveRatePolicy request: %w", err)
   490  	}
   491  
   492  	var result RemoveRatePolicyResponse
   493  	resp, err := p.Exec(req, &result)
   494  	if err != nil {
   495  		return nil, fmt.Errorf("remove rate policy request failed: %w", err)
   496  	}
   497  	if resp.StatusCode != http.StatusNoContent && resp.StatusCode != http.StatusOK {
   498  		return nil, p.Error(resp)
   499  	}
   500  
   501  	return &result, nil
   502  }