better 429 messages for both share/enable when over limit

This commit is contained in:
Michael Quigley 2025-06-23 21:16:01 -04:00
parent 3c637d9a4b
commit 176759624d
No known key found for this signature in database
GPG Key ID: 9B60314A9DD20A62
11 changed files with 187 additions and 14 deletions

View File

@ -29,7 +29,7 @@ func (h *enableHandler) Handle(params environment.EnableParams, principal *rest_
if err := h.checkLimits(principal, trx); err != nil { if err := h.checkLimits(principal, trx); err != nil {
logrus.Errorf("limits error for user '%v': %v", principal.Email, err) logrus.Errorf("limits error for user '%v': %v", principal.Email, err)
return environment.NewEnableUnauthorized() return environment.NewEnableTooManyRequests().WithPayload("too many environments; account limit exceeded")
} }
client, err := zrokEdgeSdk.Client(cfg.Ziti) client, err := zrokEdgeSdk.Client(cfg.Ziti)

View File

@ -23,8 +23,6 @@ func newShareHandler() *shareHandler {
} }
func (h *shareHandler) Handle(params share.ShareParams, principal *rest_model_zrok.Principal) middleware.Responder { func (h *shareHandler) Handle(params share.ShareParams, principal *rest_model_zrok.Principal) middleware.Responder {
logrus.Info("handling")
trx, err := str.Begin() trx, err := str.Begin()
if err != nil { if err != nil {
logrus.Errorf("error starting transaction: %v", err) logrus.Errorf("error starting transaction: %v", err)
@ -40,7 +38,7 @@ func (h *shareHandler) Handle(params share.ShareParams, principal *rest_model_zr
if err := h.checkLimits(envId, principal, params.Body.Reserved, params.Body.UniqueName != "", sdk.ShareMode(params.Body.ShareMode), sdk.BackendMode(params.Body.BackendMode), trx); err != nil { if err := h.checkLimits(envId, principal, params.Body.Reserved, params.Body.UniqueName != "", sdk.ShareMode(params.Body.ShareMode), sdk.BackendMode(params.Body.BackendMode), trx); err != nil {
logrus.Errorf("limits error for '%v': %v", principal.Email, err) logrus.Errorf("limits error for '%v': %v", principal.Email, err)
return share.NewShareTooManyRequests() return share.NewShareTooManyRequests().WithPayload("too many shares; account limit exceeded")
} }
accessGrantAcctIds, err := h.processAccessGrants(params, principal, trx) accessGrantAcctIds, err := h.processAccessGrants(params, principal, trx)
@ -51,7 +49,7 @@ func (h *shareHandler) Handle(params share.ShareParams, principal *rest_model_zr
edge, err := zrokEdgeSdk.Client(cfg.Ziti) edge, err := zrokEdgeSdk.Client(cfg.Ziti)
if err != nil { if err != nil {
logrus.Error(err) logrus.Errorf("error getting ziti management client: %v", err)
return share.NewShareInternalServerError() return share.NewShareInternalServerError()
} }

View File

@ -13,6 +13,8 @@ import (
"github.com/go-openapi/runtime" "github.com/go-openapi/runtime"
"github.com/go-openapi/strfmt" "github.com/go-openapi/strfmt"
"github.com/go-openapi/swag" "github.com/go-openapi/swag"
"github.com/openziti/zrok/rest_model_zrok"
) )
// EnableReader is a Reader for the Enable structure. // EnableReader is a Reader for the Enable structure.
@ -41,6 +43,12 @@ func (o *EnableReader) ReadResponse(response runtime.ClientResponse, consumer ru
return nil, err return nil, err
} }
return nil, result return nil, result
case 429:
result := NewEnableTooManyRequests()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
case 500: case 500:
result := NewEnableInternalServerError() result := NewEnableInternalServerError()
if err := result.readResponse(response, consumer, o.formats); err != nil { if err := result.readResponse(response, consumer, o.formats); err != nil {
@ -232,6 +240,72 @@ func (o *EnableNotFound) readResponse(response runtime.ClientResponse, consumer
return nil return nil
} }
// NewEnableTooManyRequests creates a EnableTooManyRequests with default headers values
func NewEnableTooManyRequests() *EnableTooManyRequests {
return &EnableTooManyRequests{}
}
/*
EnableTooManyRequests describes a response with status code 429, with default header values.
over limit
*/
type EnableTooManyRequests struct {
Payload rest_model_zrok.ErrorMessage
}
// IsSuccess returns true when this enable too many requests response has a 2xx status code
func (o *EnableTooManyRequests) IsSuccess() bool {
return false
}
// IsRedirect returns true when this enable too many requests response has a 3xx status code
func (o *EnableTooManyRequests) IsRedirect() bool {
return false
}
// IsClientError returns true when this enable too many requests response has a 4xx status code
func (o *EnableTooManyRequests) IsClientError() bool {
return true
}
// IsServerError returns true when this enable too many requests response has a 5xx status code
func (o *EnableTooManyRequests) IsServerError() bool {
return false
}
// IsCode returns true when this enable too many requests response a status code equal to that given
func (o *EnableTooManyRequests) IsCode(code int) bool {
return code == 429
}
// Code gets the status code for the enable too many requests response
func (o *EnableTooManyRequests) Code() int {
return 429
}
func (o *EnableTooManyRequests) Error() string {
return fmt.Sprintf("[POST /enable][%d] enableTooManyRequests %+v", 429, o.Payload)
}
func (o *EnableTooManyRequests) String() string {
return fmt.Sprintf("[POST /enable][%d] enableTooManyRequests %+v", 429, o.Payload)
}
func (o *EnableTooManyRequests) GetPayload() rest_model_zrok.ErrorMessage {
return o.Payload
}
func (o *EnableTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
// response payload
if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF {
return err
}
return nil
}
// NewEnableInternalServerError creates a EnableInternalServerError with default headers values // NewEnableInternalServerError creates a EnableInternalServerError with default headers values
func NewEnableInternalServerError() *EnableInternalServerError { func NewEnableInternalServerError() *EnableInternalServerError {
return &EnableInternalServerError{} return &EnableInternalServerError{}

View File

@ -373,6 +373,7 @@ ShareTooManyRequests describes a response with status code 429, with default hea
over limit over limit
*/ */
type ShareTooManyRequests struct { type ShareTooManyRequests struct {
Payload rest_model_zrok.ErrorMessage
} }
// IsSuccess returns true when this share too many requests response has a 2xx status code // IsSuccess returns true when this share too many requests response has a 2xx status code
@ -406,15 +407,24 @@ func (o *ShareTooManyRequests) Code() int {
} }
func (o *ShareTooManyRequests) Error() string { func (o *ShareTooManyRequests) Error() string {
return fmt.Sprintf("[POST /share][%d] shareTooManyRequests ", 429) return fmt.Sprintf("[POST /share][%d] shareTooManyRequests %+v", 429, o.Payload)
} }
func (o *ShareTooManyRequests) String() string { func (o *ShareTooManyRequests) String() string {
return fmt.Sprintf("[POST /share][%d] shareTooManyRequests ", 429) return fmt.Sprintf("[POST /share][%d] shareTooManyRequests %+v", 429, o.Payload)
}
func (o *ShareTooManyRequests) GetPayload() rest_model_zrok.ErrorMessage {
return o.Payload
} }
func (o *ShareTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { func (o *ShareTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
// response payload
if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF {
return err
}
return nil return nil
} }

View File

@ -1020,6 +1020,12 @@ func init() {
"404": { "404": {
"description": "account not found" "description": "account not found"
}, },
"429": {
"description": "over limit",
"schema": {
"$ref": "#/definitions/errorMessage"
}
},
"500": { "500": {
"description": "internal server error" "description": "internal server error"
} }
@ -2299,7 +2305,10 @@ func init() {
"description": "unprocessable" "description": "unprocessable"
}, },
"429": { "429": {
"description": "over limit" "description": "over limit",
"schema": {
"$ref": "#/definitions/errorMessage"
}
}, },
"500": { "500": {
"description": "internal server error", "description": "internal server error",
@ -3970,6 +3979,12 @@ func init() {
"404": { "404": {
"description": "account not found" "description": "account not found"
}, },
"429": {
"description": "over limit",
"schema": {
"$ref": "#/definitions/errorMessage"
}
},
"500": { "500": {
"description": "internal server error" "description": "internal server error"
} }
@ -5198,7 +5213,10 @@ func init() {
"description": "unprocessable" "description": "unprocessable"
}, },
"429": { "429": {
"description": "over limit" "description": "over limit",
"schema": {
"$ref": "#/definitions/errorMessage"
}
}, },
"500": { "500": {
"description": "internal server error", "description": "internal server error",

View File

@ -9,6 +9,8 @@ import (
"net/http" "net/http"
"github.com/go-openapi/runtime" "github.com/go-openapi/runtime"
"github.com/openziti/zrok/rest_model_zrok"
) )
// EnableCreatedCode is the HTTP code returned for type EnableCreated // EnableCreatedCode is the HTTP code returned for type EnableCreated
@ -106,6 +108,49 @@ func (o *EnableNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.
rw.WriteHeader(404) rw.WriteHeader(404)
} }
// EnableTooManyRequestsCode is the HTTP code returned for type EnableTooManyRequests
const EnableTooManyRequestsCode int = 429
/*
EnableTooManyRequests over limit
swagger:response enableTooManyRequests
*/
type EnableTooManyRequests struct {
/*
In: Body
*/
Payload rest_model_zrok.ErrorMessage `json:"body,omitempty"`
}
// NewEnableTooManyRequests creates EnableTooManyRequests with default headers values
func NewEnableTooManyRequests() *EnableTooManyRequests {
return &EnableTooManyRequests{}
}
// WithPayload adds the payload to the enable too many requests response
func (o *EnableTooManyRequests) WithPayload(payload rest_model_zrok.ErrorMessage) *EnableTooManyRequests {
o.Payload = payload
return o
}
// SetPayload sets the payload to the enable too many requests response
func (o *EnableTooManyRequests) SetPayload(payload rest_model_zrok.ErrorMessage) {
o.Payload = payload
}
// WriteResponse to the client
func (o *EnableTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
rw.WriteHeader(429)
payload := o.Payload
if err := producer.Produce(rw, payload); err != nil {
panic(err) // let the recovery middleware deal with this
}
}
// EnableInternalServerErrorCode is the HTTP code returned for type EnableInternalServerError // EnableInternalServerErrorCode is the HTTP code returned for type EnableInternalServerError
const EnableInternalServerErrorCode int = 500 const EnableInternalServerErrorCode int = 500

View File

@ -167,6 +167,11 @@ ShareTooManyRequests over limit
swagger:response shareTooManyRequests swagger:response shareTooManyRequests
*/ */
type ShareTooManyRequests struct { type ShareTooManyRequests struct {
/*
In: Body
*/
Payload rest_model_zrok.ErrorMessage `json:"body,omitempty"`
} }
// NewShareTooManyRequests creates ShareTooManyRequests with default headers values // NewShareTooManyRequests creates ShareTooManyRequests with default headers values
@ -175,12 +180,25 @@ func NewShareTooManyRequests() *ShareTooManyRequests {
return &ShareTooManyRequests{} return &ShareTooManyRequests{}
} }
// WithPayload adds the payload to the share too many requests response
func (o *ShareTooManyRequests) WithPayload(payload rest_model_zrok.ErrorMessage) *ShareTooManyRequests {
o.Payload = payload
return o
}
// SetPayload sets the payload to the share too many requests response
func (o *ShareTooManyRequests) SetPayload(payload rest_model_zrok.ErrorMessage) {
o.Payload = payload
}
// WriteResponse to the client // WriteResponse to the client
func (o *ShareTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { func (o *ShareTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses
rw.WriteHeader(429) rw.WriteHeader(429)
payload := o.Payload
if err := producer.Produce(rw, payload); err != nil {
panic(err) // let the recovery middleware deal with this
}
} }
// ShareInternalServerErrorCode is the HTTP code returned for type ShareInternalServerError // ShareInternalServerErrorCode is the HTTP code returned for type ShareInternalServerError

View File

@ -156,6 +156,7 @@ Name | Type | Description | Notes
**201** | environment enabled | - | **201** | environment enabled | - |
**401** | unauthorized | - | **401** | unauthorized | - |
**404** | account not found | - | **404** | account not found | - |
**429** | over limit | - |
**500** | internal server error | - | **500** | internal server error | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)

View File

@ -365,6 +365,7 @@ class EnvironmentApi:
'201': "CreateIdentity201Response", '201': "CreateIdentity201Response",
'401': None, '401': None,
'404': None, '404': None,
'429': "str",
'500': None, '500': None,
} }
response_data = self.api_client.call_api( response_data = self.api_client.call_api(
@ -434,6 +435,7 @@ class EnvironmentApi:
'201': "CreateIdentity201Response", '201': "CreateIdentity201Response",
'401': None, '401': None,
'404': None, '404': None,
'429': "str",
'500': None, '500': None,
} }
response_data = self.api_client.call_api( response_data = self.api_client.call_api(
@ -503,6 +505,7 @@ class EnvironmentApi:
'201': "CreateIdentity201Response", '201': "CreateIdentity201Response",
'401': None, '401': None,
'404': None, '404': None,
'429': "str",
'500': None, '500': None,
} }
response_data = self.api_client.call_api( response_data = self.api_client.call_api(

View File

@ -382,7 +382,7 @@ class ShareApi:
'404': None, '404': None,
'409': None, '409': None,
'422': None, '422': None,
'429': None, '429': "str",
'500': "str", '500': "str",
} }
response_data = self.api_client.call_api( response_data = self.api_client.call_api(
@ -454,7 +454,7 @@ class ShareApi:
'404': None, '404': None,
'409': None, '409': None,
'422': None, '422': None,
'429': None, '429': "str",
'500': "str", '500': "str",
} }
response_data = self.api_client.call_api( response_data = self.api_client.call_api(
@ -526,7 +526,7 @@ class ShareApi:
'404': None, '404': None,
'409': None, '409': None,
'422': None, '422': None,
'429': None, '429': "str",
'500': "str", '500': "str",
} }
response_data = self.api_client.call_api( response_data = self.api_client.call_api(

View File

@ -1026,6 +1026,10 @@ paths:
description: unauthorized description: unauthorized
404: 404:
description: account not found description: account not found
429:
description: over limit
schema:
$ref: "#/definitions/errorMessage"
500: 500:
description: internal server error description: internal server error
@ -1499,6 +1503,8 @@ paths:
description: unprocessable description: unprocessable
429: 429:
description: over limit description: over limit
schema:
$ref: "#/definitions/errorMessage"
500: 500:
description: internal server error description: internal server error
schema: schema: