Skip to content

Commit

Permalink
utility handler fn extraction
Browse files Browse the repository at this point in the history
  • Loading branch information
danicc097 committed Jan 19, 2025
1 parent 819f6f6 commit f6a5d18
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 26 deletions.
23 changes: 3 additions & 20 deletions internal/rest/api_work_item.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
package rest

import (
"bytes"
"encoding/json"
"io"
"net/http"

"github.com/danicc097/openapi-go-gin-postgres-sqlc/internal"
"github.com/danicc097/openapi-go-gin-postgres-sqlc/internal/repos"
"github.com/danicc097/openapi-go-gin-postgres-sqlc/internal/repos/postgresql/gen/models"
"github.com/danicc097/openapi-go-gin-postgres-sqlc/internal/services"
"github.com/danicc097/openapi-go-gin-postgres-sqlc/internal/tracing"
"github.com/gin-gonic/gin"
)

Expand All @@ -29,28 +26,14 @@ func (h *StrictHandlers) DeleteWorkitem(c *gin.Context, request DeleteWorkitemRe
func (h *StrictHandlers) CreateWorkitem(c *gin.Context, request CreateWorkitemRequestObject) (CreateWorkitemResponseObject, error) {
ctx := c.Request.Context()

span := GetSpanFromCtx(c)

caller, _ := GetUserCallerFromCtx(c)
tx := GetTxFromCtx(c)

jsonBody, err := io.ReadAll(c.Request.Body)
if err != nil {
renderErrorResponse(c, "Failed to read request body", err)
}
span.SetAttributes(tracing.MetadataAttribute(jsonBody))
c.Request.Body = io.NopCloser(bytes.NewBuffer(jsonBody))

project, err := projectByDiscriminator(request.Body)
if err != nil {
renderErrorResponse(c, "Failed to get project", err)
}
addRequestBodyToSpan(c)

var res any // depends on project
b, err := request.Body.ValueByDiscriminator()
if err != nil {
renderErrorResponse(c, "Failed to read discriminator", err)
}

project, b := projectAndBodyByDiscriminator(c, request.Body)

//exhaustive:enforce
switch project {
Expand Down
17 changes: 11 additions & 6 deletions internal/rest/discriminator.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
package rest

import (
"fmt"

"github.com/danicc097/openapi-go-gin-postgres-sqlc/internal/repos/postgresql/gen/models"
"github.com/gin-gonic/gin"
)

type PolymorphicBody interface {
Discriminator() (string, error)
ValueByDiscriminator() (interface{}, error)
}

func projectByDiscriminator(b PolymorphicBody) (models.ProjectName, error) {
d, err := b.Discriminator()
func projectAndBodyByDiscriminator(c *gin.Context, body PolymorphicBody) (models.ProjectName, interface{}) {
d, err := body.Discriminator()
if err != nil {
renderErrorResponse(c, "could not get project discriminator: %w", err)
}

b, err := body.ValueByDiscriminator()
if err != nil {
return "", fmt.Errorf("could not get project discriminator: %w", err)
renderErrorResponse(c, "Failed to read discriminator", err)
}

return models.ProjectName(d), nil
return models.ProjectName(d), b
}
14 changes: 14 additions & 0 deletions internal/rest/otel.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package rest

import (
"bytes"
"io"

"github.com/danicc097/openapi-go-gin-postgres-sqlc/internal"
"github.com/danicc097/openapi-go-gin-postgres-sqlc/internal/tracing"
"github.com/gin-gonic/gin"
Expand Down Expand Up @@ -38,3 +41,14 @@ func newOTelSpanWithUser(c *gin.Context, opts ...trace.SpanStartOption) trace.Sp

return builder.Build(c.Request.Context())
}

func addRequestBodyToSpan(c *gin.Context) {
span := GetSpanFromCtx(c)

jsonBody, err := io.ReadAll(c.Request.Body)
if err != nil {
renderErrorResponse(c, "Failed to read request body", err)
}
span.SetAttributes(tracing.MetadataAttribute(jsonBody))
c.Request.Body = io.NopCloser(bytes.NewBuffer(jsonBody))
}
3 changes: 3 additions & 0 deletions internal/rest/responses.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ func WithoutPanic() RenderErrorOption {
}

// renderErrorResponse writes an error response from title and error.
// When used inside a StrictHandlers' handler, it panics with a HandlerExitError which
// is recovered immediately by the handler wrapper.
// When used outside a StrictHandlers' handler, WithoutPanic must be used to prevent unrecovered panics.
// title represents an error title which will be shown to end users.
// Inspired by https://www.rfc-editor.org/rfc/rfc7807.
func renderErrorResponse(c *gin.Context, title string, err error, opts ...RenderErrorOption) {
Expand Down

0 comments on commit f6a5d18

Please sign in to comment.