Skip to content

Commit

Permalink
refactor(issue-55): do not force users to return an interface
Browse files Browse the repository at this point in the history
  • Loading branch information
Zaba505 committed Jan 18, 2025
1 parent 0293de0 commit 21b8dfa
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 38 deletions.
2 changes: 1 addition & 1 deletion example/petstore/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type Config struct {
rest.Config `config:",squash"`
}

func Init(ctx context.Context, cfg Config) (rest.Api, error) {
func Init(ctx context.Context, cfg Config) (*mux.Router, error) {
m := mux.New(
cfg.OpenApi.Title,
cfg.OpenApi.Version,
Expand Down
20 changes: 20 additions & 0 deletions example/petstore/endpoint/endpoint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (c) 2025 Z5Labs and Contributors
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT

package endpoint

import "github.com/z5labs/humus/rest/mux"

type Router interface {
Route(method, pattern string, op mux.Operation) error
}

func mustRoute(r Router, method, pattern string, op mux.Operation) {
err := r.Route(method, pattern, op)
if err == nil {
return
}
panic(err)
}
13 changes: 9 additions & 4 deletions example/petstore/endpoint/register_pet.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"github.com/z5labs/humus/example/petstore/pet"
"go.opentelemetry.io/otel"

"github.com/z5labs/humus/rest/mux"
"github.com/z5labs/humus/rest/rpc"
)

Expand All @@ -24,19 +23,25 @@ type registerPetHandler struct {
store RegisterPetStore
}

func RegisterPet(m mux.Muxer, store RegisterPetStore) {
func RegisterPet(r Router, store RegisterPetStore) {
h := &registerPetHandler{
store: store,
}

mux.MustRoute(
m,
mustRoute(
r,
http.MethodPost,
"/pet/register",
rpc.NewOperation(
rpc.ConsumesJson(
rpc.ProducesJson(h),
),
rpc.Header(

Check failure on line 39 in example/petstore/endpoint/register_pet.go

View workflow job for this annotation

GitHub Actions / Build

undefined: rpc.Header

Check failure on line 39 in example/petstore/endpoint/register_pet.go

View workflow job for this annotation

GitHub Actions / Build

undefined: rpc.Header

Check failure on line 39 in example/petstore/endpoint/register_pet.go

View workflow job for this annotation

GitHub Actions / Update coverage badge

undefined: rpc.Header
"Authorization",
rpc.ValidateHeader(nil),

Check failure on line 41 in example/petstore/endpoint/register_pet.go

View workflow job for this annotation

GitHub Actions / Build

undefined: rpc.ValidateHeader

Check failure on line 41 in example/petstore/endpoint/register_pet.go

View workflow job for this annotation

GitHub Actions / Build

undefined: rpc.ValidateHeader

Check failure on line 41 in example/petstore/endpoint/register_pet.go

View workflow job for this annotation

GitHub Actions / Update coverage badge

undefined: rpc.ValidateHeader
),
rpc.QueryParam("start"),

Check failure on line 43 in example/petstore/endpoint/register_pet.go

View workflow job for this annotation

GitHub Actions / Build

undefined: rpc.QueryParam

Check failure on line 43 in example/petstore/endpoint/register_pet.go

View workflow job for this annotation

GitHub Actions / Build

undefined: rpc.QueryParam

Check failure on line 43 in example/petstore/endpoint/register_pet.go

View workflow job for this annotation

GitHub Actions / Update coverage badge

undefined: rpc.QueryParam
rpc.PathParam("id"),

Check failure on line 44 in example/petstore/endpoint/register_pet.go

View workflow job for this annotation

GitHub Actions / Build

undefined: rpc.PathParam (typecheck)

Check failure on line 44 in example/petstore/endpoint/register_pet.go

View workflow job for this annotation

GitHub Actions / Build

undefined: rpc.PathParam) (typecheck)

Check failure on line 44 in example/petstore/endpoint/register_pet.go

View workflow job for this annotation

GitHub Actions / Update coverage badge

undefined: rpc.PathParam
),
)
}
Expand Down
19 changes: 0 additions & 19 deletions rest/mux/mux.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (

"github.com/z5labs/humus"
"github.com/z5labs/humus/health"
"github.com/z5labs/humus/rest"
"github.com/z5labs/humus/rest/embedded"

"github.com/go-chi/chi/v5"
Expand Down Expand Up @@ -87,10 +86,6 @@ type router interface {
Method(string, string, http.Handler)
}

// always ensure [Router] implements the [rest.Api] interface.
// if [Api] is ever changed this will lead to compilation error here.
var _ rest.Api = (*Router)(nil)

// Router is a HTTP request multiplexer which implements the [rest.Api] interface.
//
// Router provides a set of standard features:
Expand Down Expand Up @@ -183,20 +178,6 @@ type Operation interface {
Definition() (openapi3.Operation, error)
}

// Muxer
type Muxer interface {
Route(method, pattern string, op Operation) error
}

// MustRoute
func MustRoute(m Muxer, method, pattern string, op Operation) {
err := m.Route(method, pattern, op)
if err == nil {
return
}
panic(err)
}

// Route will configure any request matching method and pattern to be
// handled by the provided [Operation]. It will also register the [Operation]
// with an underlying OpenAPI 3.0 schema.
Expand Down
10 changes: 8 additions & 2 deletions rest/mux/mux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,14 @@ func TestRouter_ServeHTTP(t *testing.T) {
})),
)

MustRoute(r, http.MethodGet, "/", noopDefinition{
err := r.Route(http.MethodGet, "/", noopDefinition{
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}),
})
if !assert.Nil(t, err) {
return
}

w := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/hello", nil)
Expand All @@ -109,11 +112,14 @@ func TestRouter_ServeHTTP(t *testing.T) {
})),
)

MustRoute(r, http.MethodGet, "/", noopDefinition{
err := r.Route(http.MethodGet, "/", noopDefinition{
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}),
})
if !assert.Nil(t, err) {
return
}

w := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(``))
Expand Down
17 changes: 5 additions & 12 deletions rest/rest.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
"github.com/z5labs/humus/buildcontext"
"github.com/z5labs/humus/internal"
"github.com/z5labs/humus/internal/httpserver"
"github.com/z5labs/humus/rest/embedded"
"github.com/z5labs/humus/rest/mux"

"github.com/z5labs/bedrock"
"github.com/z5labs/bedrock/app"
Expand Down Expand Up @@ -71,13 +71,6 @@ func (c Config) HttpServer(ctx context.Context, h http.Handler) (*http.Server, e
return s, nil
}

// Api represents a HTTP handler which implements a RESTful API.
type Api interface {
embedded.Api

http.Handler
}

// BuildContext represents more dynamic properties of the app building
// process such as lifecycle hooks and OS signal interrupts.
type BuildContext struct {
Expand All @@ -103,12 +96,12 @@ func (bc *BuildContext) InterruptOn(signals ...os.Signal) {
}

// Run begins by reading, parsing and unmarshaling your custom config into
// the type T. Then it calls the providing function to initialize your [Api]
// implementation. Once it has the [Api] implementation, it begins serving
// the [Api] over HTTP. Various middlewares are applied at different stages
// the type T. Then it calls the providing function to initialize your [mux.Router]
// implementation. Once it has the [mux.Router] implementation, it begins serving
// the [mux.Router] over HTTP. Various middlewares are applied at different stages
// for your convenience. Some middlewares include, automattic panic recovery,
// OTel SDK initialization and shutdown, and OS signal based shutdown.
func Run[T Configer](r io.Reader, f func(context.Context, T) (Api, error)) {
func Run[T Configer](r io.Reader, f func(context.Context, T) (*mux.Router, error)) {
err := bedrock.Run(
context.Background(),
// OTel middleware will handle shutting down OTel SDK components on PostRun
Expand Down

0 comments on commit 21b8dfa

Please sign in to comment.