Skip to content

Commit

Permalink
feat: add WithRequestContentType config option for the Server
Browse files Browse the repository at this point in the history
  • Loading branch information
dylanhitt committed Oct 24, 2024
1 parent fb0ea00 commit e2eabcf
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 0 deletions.
1 change: 1 addition & 0 deletions mux.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ func registerFuegoController[T, B any, Contexted ctx[B]](s *Server, method, path
if route.MainRouter == nil {
route.MainRouter = s
}
route.AcceptedContentTypes = route.MainRouter.acceptedContentTypes

for _, o := range options {
o(&route)
Expand Down
1 change: 1 addition & 0 deletions option/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ func AddError(code int, description string, errorType ...any) func(*fuego.BaseRo

// RequestContentType sets the accepted content types for the route.
// By default, the accepted content types is */*.
// This will override any options set at the server level.
func RequestContentType(consumes ...string) func(*fuego.BaseRoute) {
return func(r *fuego.BaseRoute) {
r.AcceptedContentTypes = consumes
Expand Down
16 changes: 16 additions & 0 deletions option/option_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,22 @@ func TestRequestContentType(t *testing.T) {
_, ok := s.OpenApiSpec.Components.RequestBodies["ReqBody"]
require.False(t, ok)
})

t.Run("override server", func(t *testing.T) {
s := fuego.NewServer(fuego.WithRequestContentType("application/json", "application/xml"))
route := fuego.Post(
s, "/test", dummyController,
RequestContentType("my/content-type"),
)

content := route.Operation.RequestBody.Value.Content
require.Nil(t, content.Get("application/json"))
require.Nil(t, content.Get("application/xml"))
require.NotNil(t, content.Get("my/content-type"))
require.Equal(t, "#/components/schemas/ReqBody", content.Get("my/content-type").Schema.Ref)
_, ok := s.OpenApiSpec.Components.RequestBodies["ReqBody"]
require.False(t, ok)
})
}

func TestAddError(t *testing.T) {
Expand Down
8 changes: 8 additions & 0 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ type Server struct {
fs fs.FS
template *template.Template // TODO: use preparsed templates

acceptedContentTypes []string

DisallowUnknownFields bool // If true, the server will return an error if the request body contains unknown fields. Useful for quick debugging in development.
DisableOpenapi bool // If true, the routes within the server will not generate an OpenAPI spec.
maxBodySize int64
Expand Down Expand Up @@ -307,6 +309,12 @@ func WithLogHandler(handler slog.Handler) func(*Server) {
}
}

// WithRequestContentType sets the accepted content types for the server.
// By default, the accepted content types is */*.
func WithRequestContentType(consumes ...string) func(*Server) {
return func(s *Server) { s.acceptedContentTypes = consumes }
}

// WithSerializer sets a custom serializer of type Sender that overrides the default one.
// Please send a PR if you think the default serializer should be improved, instead of jumping to this option.
func WithSerializer(serializer Sender) func(*Server) {
Expand Down
39 changes: 39 additions & 0 deletions options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,45 @@ func TestServerTags(t *testing.T) {
})
}

type ReqBody struct {
A string
B int
}

type Resp struct {
Message string `json:"message"`
}

func dummyController(_ *ContextWithBody[ReqBody]) (Resp, error) {
return Resp{Message: "hello world"}, nil
}

func TestWithRequestContentType(t *testing.T) {
t.Run("base", func(t *testing.T) {
s := NewServer()
require.Nil(t, s.acceptedContentTypes)
})

t.Run("input", func(t *testing.T) {
arr := []string{"application/json", "application/xml"}
s := NewServer(WithRequestContentType("application/json", "application/xml"))
require.ElementsMatch(t, arr, s.acceptedContentTypes)
})

t.Run("ensure applied to route", func(t *testing.T) {
s := NewServer(WithRequestContentType("application/json", "application/xml"))
route := Post(s, "/test", dummyController)

content := route.Operation.RequestBody.Value.Content
require.NotNil(t, content.Get("application/json"))
require.NotNil(t, content.Get("application/xml"))
require.Equal(t, "#/components/schemas/ReqBody", content.Get("application/json").Schema.Ref)
require.Equal(t, "#/components/schemas/ReqBody", content.Get("application/xml").Schema.Ref)
_, ok := s.OpenApiSpec.Components.RequestBodies["ReqBody"]
require.False(t, ok)
})
}

func TestCustomSerialization(t *testing.T) {
s := NewServer(
WithSerializer(func(w http.ResponseWriter, r *http.Request, a any) error {
Expand Down

0 comments on commit e2eabcf

Please sign in to comment.