-
Notifications
You must be signed in to change notification settings - Fork 11
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
refactor: separate validation, response and business logic #1301
base: staging
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Linter job fails:
Check failure on line 100 in backend/pkg/api/handlers/input_validation.go
printf: non-constant format string in call to
github.com/gobitfly/beaconchain/pkg/api/handlers.newBadRequestErr
Check failure on line 156 in backend/pkg/api/handlers/input_validation.go
unnecessary leading newline (whitespace)
ee1c378
to
35649cc
Compare
35649cc
to
def1b01
Compare
…oardGroupSummary` logics
def1b01
to
f58c2e6
Compare
714ef42
to
500906e
Compare
Deploying beaconchain with
|
Latest commit: |
500906e
|
Status: | ✅ Deploy successful! |
Preview URL: | https://3d82629b.beaconchain.pages.dev |
Branch Preview URL: | https://beds-94-abstract-handle-test.beaconchain.pages.dev |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I got it right, handlers/public.go
can be removed entirely once your suggestion is applied to all functions, right? That would be so great
type Checker[T any] interface { | ||
Check(params map[string]string, payload io.ReadCloser) (T, error) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Imo it's worth re-thinking naming for the interface and method name here, Check(er)
is a bit vague. It's only supposed to be used in the context of input validation, right? Maybe InputValidator
and Validate()
or so
if contentType := r.Header.Get("Content-Type"); !reJsonContentType.MatchString(contentType) { | ||
v.add("request body", "'Content-Type' header must be 'application/json'") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couldn't this check be kept somehow? Maybe move it to middleware, like if there is a body present it should be application/json
|
||
bodyBytes, err := io.ReadAll(r.Body) | ||
r.Body = io.NopCloser(bytes.NewReader(bodyBytes)) // unconsume body for error logging | ||
func (v *validationError) checkBody(data interface{}, requestBody io.ReadCloser) error { // <- should be checkBody after refactoring |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
func (v *validationError) checkBody(data interface{}, requestBody io.ReadCloser) error { // <- should be checkBody after refactoring | |
func (v *validationError) checkBody(data interface{}, requestBody io.ReadCloser) error { |
@@ -560,3 +561,28 @@ func (v *validationError) checkTimestamps(r *http.Request, chartLimits ChartTime | |||
return afterTs, beforeTs | |||
} | |||
} | |||
|
|||
func (v *validationError) checkDashboardId(id string) interface{} { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks essentially like the same as https://github.com/gobitfly/beaconchain/blob/staging/backend/pkg/api/handlers/handler_service.go#L85-L109 to me, what's the reason for this? Would be cool if it was possible to merge them
"github.com/gobitfly/beaconchain/pkg/api/types" | ||
) | ||
|
||
// PublicPostValidatorDashboardGroups godoc |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
check: I think doc generation doesn't work anymore since the method name changed
} | ||
|
||
func (h *HandlerService) PostValidatorDashboardGroups(ctx context.Context, input inputPostValidatorDashboardGroups) (*types.ApiDataResponse[types.VDBPostCreateGroupData], error) { | ||
dataAccessor := h.getDataAccessor(ctx) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This step will exist in virtually every business logic func, right? Could you think of a clean way to also inject this via handler_service.Handle()
, I think that would be cool
func stringAsBody(s string) io.ReadCloser { | ||
return io.NopCloser(strings.NewReader(s)) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this will be used in other unit test files, too. Maybe such helpers should be placed in a new/existing common file (prob same for handlerTestSetup()
)
return ctx, NewHandlerService(da, da, nil, false) | ||
} | ||
|
||
func TestPostValidatorDashboardGroups(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at the split of tests into input validation and business logic: Maybe both could be grouped under one test method which is responsible for the entire api call, and then either use subsubtests or just do input first and business logic after.
What do you think? Collapsing entire units at once could be nice dev qol
Adds a pattern for splitting the HTTP logic from the business logic in the API handler funcs. Adds a few example test cases. Changes the test workflow to include these tests.