diff --git a/cloudevents/service.go b/cloudevents/service.go index d7c2a59..a99047a 100644 --- a/cloudevents/service.go +++ b/cloudevents/service.go @@ -60,7 +60,7 @@ func New(f any) *Service { mux.HandleFunc("/health/readiness", svc.Ready) mux.HandleFunc("/health/liveness", svc.Alive) mux.Handle("/", newCloudeventHandler(f)) // See implementation note - svc.Server.Handler = mux + svc.Handler = mux return svc } @@ -91,7 +91,7 @@ func (s *Service) Start(ctx context.Context) (err error) { s.handleSignals() go func() { - if err = s.Server.Serve(s.listener); err != http.ErrServerClosed { + if err := s.Serve(s.listener); err != http.ErrServerClosed { log.Error().Err(err).Msg("http server exited with unexpected error") s.stop <- err } diff --git a/cmd/fhttp/main.go b/cmd/fhttp/main.go index 57617c5..7911f39 100644 --- a/cmd/fhttp/main.go +++ b/cmd/fhttp/main.go @@ -1,7 +1,6 @@ package main import ( - "context" "fmt" "net/http" "os" @@ -25,9 +24,9 @@ func main() { } // Example Static HTTP Handler implementation. -func Handle(ctx context.Context, res http.ResponseWriter, req *http.Request) { +func Handle(w http.ResponseWriter, r *http.Request) { fmt.Println("Static HTTP handler invoked") - res.Write([]byte("Static HTTP handler invoked\n")) + fmt.Fprintln(w, "Static HTTP Handler invoked") } // MyFunction is an example instanced HTTP function implementation. @@ -37,7 +36,7 @@ func New() *MyFunction { return &MyFunction{} } -func (f *MyFunction) Handle(_ context.Context, res http.ResponseWriter, req *http.Request) { +func (f *MyFunction) Handle(w http.ResponseWriter, r *http.Request) { fmt.Println("Instanced HTTP handler invoked") - res.Write([]byte("Instanced HTTP handler invoked\n")) + fmt.Fprintln(w, "Instanced HTTP Handler invoked") } diff --git a/http/instance.go b/http/instance.go index b7750bc..d16687b 100644 --- a/http/instance.go +++ b/http/instance.go @@ -3,8 +3,6 @@ package http import ( "context" "net/http" - - "github.com/rs/zerolog/log" ) // Handler is a function instance which can handle a request. @@ -14,9 +12,11 @@ import ( // framework is the same. type Handler interface { // Handle a request. - Handle(context.Context, http.ResponseWriter, *http.Request) + Handle(http.ResponseWriter, *http.Request) } +type HandleFunc func(http.ResponseWriter, *http.Request) + // Starter is an instance which has defined the Start hook type Starter interface { // Start instance event hook. @@ -41,26 +41,12 @@ type LivenessReporter interface { Alive(context.Context) (bool, error) } -// HandleFunc defines the function signature expected of static Functions. -type HandleFunc func(context.Context, http.ResponseWriter, *http.Request) - // DefaultHandler is used for simple static function implementations which // need only define a single exported function named Handle of type HandleFunc. type DefaultHandler struct { Handler HandleFunc } -// Handle a request by passing to the handler function. -func (f DefaultHandler) Handle(ctx context.Context, res http.ResponseWriter, req *http.Request) { - if f.Handler == nil { - f.Handler = defaultHandler - } - f.Handler(ctx, res, req) -} - -// DefaultHandler is a Handler implementation which simply warns the user that -// the default handler instance was not properly initialized. -var defaultHandler = func(_ context.Context, res http.ResponseWriter, req *http.Request) { - log.Warn().Msg("no Handle method found") - http.NotFound(res, req) +func (f DefaultHandler) Handle(w http.ResponseWriter, r *http.Request) { + f.Handler(w, r) } diff --git a/http/mock/function.go b/http/mock/function.go index 87b59b3..7d0b02a 100644 --- a/http/mock/function.go +++ b/http/mock/function.go @@ -8,7 +8,7 @@ import ( type Function struct { OnStart func(context.Context, map[string]string) error OnStop func(context.Context) error - OnHandle func(context.Context, http.ResponseWriter, *http.Request) + OnHandle func(http.ResponseWriter, *http.Request) } func (f *Function) Start(ctx context.Context, cfg map[string]string) error { @@ -25,8 +25,8 @@ func (f *Function) Stop(ctx context.Context) error { return nil } -func (f *Function) Handle(ctx context.Context, w http.ResponseWriter, r *http.Request) { +func (f *Function) Handle(w http.ResponseWriter, r *http.Request) { if f.OnHandle != nil { - f.OnHandle(ctx, w, r) + f.OnHandle(w, r) } } diff --git a/http/service.go b/http/service.go index fe2321e..47d4170 100644 --- a/http/service.go +++ b/http/service.go @@ -32,7 +32,7 @@ const ( // Start an intance using a new Service // Note that for CloudEvent Handlers this effectively accepts ANY because // the actual type of the handler function is determined later. -func Start(f any) error { +func Start(f Handler) error { log.Debug().Msg("func runtime creating function instance") return New(f).Start(context.Background()) } @@ -42,11 +42,11 @@ type Service struct { http.Server listener net.Listener stop chan error - f any + f Handler } // New Service which serves the given instance. -func New(f any) *Service { +func New(f Handler) *Service { svc := &Service{ f: f, stop: make(chan error), @@ -62,7 +62,7 @@ func New(f any) *Service { mux.HandleFunc("/health/readiness", svc.Ready) mux.HandleFunc("/health/liveness", svc.Alive) mux.HandleFunc("/", svc.Handle) - svc.Server.Handler = mux + svc.Handler = mux // Print some helpful information about which interfaces the function // is correctly implementing @@ -74,9 +74,6 @@ func New(f any) *Service { // log which interfaces the function implements. // This could be more verbose for new users: func logImplements(f any) { - if _, ok := f.(Handler); ok { - log.Info().Msg("Function implements Handle") - } if _, ok := f.(Starter); ok { log.Info().Msg("Function implements Start") } @@ -123,7 +120,7 @@ func (s *Service) Start(ctx context.Context) (err error) { // Listen and serve go func() { - if err = s.Server.Serve(s.listener); err != http.ErrServerClosed { + if err := s.Serve(s.listener); err != http.ErrServerClosed { log.Error().Err(err).Msg("http server exited with unexpected error") s.stop <- err } @@ -180,13 +177,7 @@ func (s *Service) Addr() net.Addr { // Handle requests for the instance func (s *Service) Handle(w http.ResponseWriter, r *http.Request) { - if i, ok := s.f.(Handler); ok { - i.Handle(r.Context(), w, r) - } else { - message := "function does not implement Handle. Skipping invocation." - log.Debug().Msg(message) - _, _ = w.Write([]byte(message)) - } + s.f.Handle(w, r) } // Ready handles readiness checks. @@ -197,11 +188,11 @@ func (s *Service) Ready(w http.ResponseWriter, r *http.Request) { message := "error checking readiness" log.Debug().Err(err).Msg(message) w.WriteHeader(500) - _, _ = w.Write([]byte(message + ". " + err.Error())) + fmt.Fprint(w, "error checking readiness: ", err.Error()) return } if !ready { - message := "function not yet available" + message := "function not yet ready" log.Debug().Msg(message) w.WriteHeader(503) fmt.Fprintln(w, message) @@ -219,11 +210,11 @@ func (s *Service) Alive(w http.ResponseWriter, r *http.Request) { message := "error checking liveness" log.Err(err).Msg(message) w.WriteHeader(500) - _, _ = w.Write([]byte(message + ". " + err.Error())) + fmt.Fprint(w, "error checking liveness: ", err.Error()) return } if !alive { - message := "function not ready" + message := "function not alive" log.Debug().Msg(message) w.WriteHeader(503) _, _ = w.Write([]byte(message)) diff --git a/http/service_test.go b/http/service_test.go index 79b3ab0..6b8192a 100644 --- a/http/service_test.go +++ b/http/service_test.go @@ -257,7 +257,7 @@ func TestHandle_Invoked(t *testing.T) { startCh <- true return nil } - onHandle = func(_ context.Context, w http.ResponseWriter, _ *http.Request) { + onHandle = func(w http.ResponseWriter, _ *http.Request) { fmt.Fprintf(w, "OK") } ) @@ -358,7 +358,7 @@ func TestAlive_Invoked(t *testing.T) { errCh = make(chan error) startCh = make(chan any) timeoutCh = time.After(500 * time.Millisecond) - onStart = func(_ context.Context, _ map[string]string) error { + onStart = func(context.Context, map[string]string) error { startCh <- true return nil }