#
Walkthrough: Parsley Integration with GoFiber
This guide demonstrates how to integrate the Parsley dependency injection framework with the GoFiber web framework. By following this example, you'll learn how to set up a GoFiber application with dependency injection managed by Parsley, making your codebase more modular, testable, and maintainable.
#
Project Structure
The code for this example can be found at examples/integrations/gofiber it has the following structure:
gofiber
├── cmd
│ └── main.go
└── internal
├── application.go
├── modules
│ ├── fiber_module.go
│ ├── greeter_module.go
│ └── route_handlers_module.go
├── route_handlers
│ ├── greeter.go
│ └── types.go
└── services
└── greeter.go
This article describes the project's structure and the purpose of each module in detail.
#
Main Application
The main entry point of the application is in the cmd/main.go
file:
package main
import (
"context"
"github.com/matzefriedrich/parsley-docs/examples/integrations/gofiber/internal"
"github.com/matzefriedrich/parsley-docs/examples/integrations/gofiber/internal/modules"
"github.com/matzefriedrich/parsley/pkg/bootstrap"
)
func main() {
ctx := context.Background()
err := bootstrap.RunParsleyApplication(ctx, internal.NewApp,
modules.ConfigureFiber,
modules.ConfigureGreeter)
if err != nil {
panic(err)
}
}
In this file, the RunParsleyApplication
function is called to bootstrap the application. It initializes the Parsley application context and configures the GoFiber server with the necessary services and route handlers.
#
Modules
The modules
package contains the service configurations required to set up the GoFiber application. The fiber_module.go
module configures the Fiber application and registers it as a singleton service within the Parsley framework:
package modules
import (
"github.com/gofiber/fiber/v2"
"github.com/matzefriedrich/parsley/pkg/registration"
"github.com/matzefriedrich/parsley/pkg/types"
)
var _ types.ModuleFunc = ConfigureFiber
// ConfigureFiber Configures all services required by the Fiber app.
func ConfigureFiber(registry types.ServiceRegistry) error {
registration.RegisterInstance(registry, fiber.Config{
AppName: "parsley-fiber-demo",
Immutable: true,
})
registry.Register(newFiber, types.LifetimeSingleton)
registry.RegisterModule(RegisterRouteHandlers)
return nil
}
func newFiber(config fiber.Config) *fiber.App {
return fiber.New(config)
}
This configuration ensures that the Fiber instance is initialized and available for dependency injection.
#
Services
Next, the internal/services/greeter.go
file defines the Greeter
service, which returns a greeting message based on the provided name and politeness flag.
package services
import "fmt"
type Greeter interface {
SayHello(name string, polite bool) string
}
type greeter struct {
}
func (g *greeter) SayHello(name string, polite bool) string {
if polite {
return fmt.Sprintf("Good day, %s!\n", name)
} else {
return fmt.Sprintf("Hi, %s\n", name)
}
}
func NewGreeter() Greeter {
return &greeter{}
}
The Greeter
service is registered by the greeter_module.go
module.
package modules
import (
"github.com/matzefriedrich/parsley-docs/examples/integrations/gofiber/internal/services"
"github.com/matzefriedrich/parsley/pkg/types"
)
// ConfigureGreeter Configures the services.Greeter service dependencies.
func ConfigureGreeter(registry types.ServiceRegistry) error {
registry.Register(services.NewGreeter, types.LifetimeTransient)
return nil
}
#
Route Handlers
In this example, route handlers are also services, structs implementing the RouteHandler
interface, which register one or more route handlers with the Fiber application. The interface is defined as follows:
package route_handlers
import "github.com/gofiber/fiber/v2"
type RouteHandler interface {
Register(app *fiber.App)
}
The internal/route_handlers/greeter.go
file registers the route handler for the /say-hello
endpoint, which returns a greeting message based on the query parameters provided in the request. The logic for the message generation is handled by the Greeter
service, which is injected into the NewGreeterRouteHandler
method.
package route_handlers
import (
"github.com/gofiber/fiber/v2"
"github.com/matzefriedrich/parsley-docs/examples/integrations/gofiber/internal/services"
)
type greeterRouteHandler struct {
greeter services.Greeter
}
// Register Registers all greeterRouteHandler route handlers.
func (h *greeterRouteHandler) Register(app *fiber.App) {
app.Get("/say-hello", h.HandleSayHelloRequest)
}
// HandleSayHelloRequest Handles "GET /say-hello" requests.
func (h *greeterRouteHandler) HandleSayHelloRequest(ctx *fiber.Ctx) error {
name := ctx.Query("name")
msg := h.greeter.SayHello(name, true)
ctx.Send([]byte(msg))
return ctx.SendStatus(fiber.StatusOK)
}
var _ RouteHandler = &greeterRouteHandler{}
func NewGreeterRouteHandler(greeter services.Greeter) RouteHandler {
return &greeterRouteHandler{
greeter: greeter,
}
}
The route_handler_module.go
file handles the registration of the RouteHandler
services themselves.
package modules
import (
"github.com/matzefriedrich/parsley-docs/examples/integrations/gofiber/internal/route_handlers"
"github.com/matzefriedrich/parsley/pkg/features"
"github.com/matzefriedrich/parsley/pkg/registration"
"github.com/matzefriedrich/parsley/pkg/types"
)
// RegisterRouteHandlers Registers all route handlers of the GoFiber app.
func RegisterRouteHandlers(registry types.ServiceRegistry) error {
features.RegisterList[route_handlers.RouteHandler](registry)
registration.RegisterTransient(registry, route_handlers.NewGreeterRouteHandler)
return nil
}
This configuration ensures that all route handlers the application requires are correctly registered and injected into the Fiber application instance. Since the application service expects a set of route handler services, the RegisterList
method must be used to register a list activator for the RouteHandler
type.
#
Application Logic
The internal/application.go
file contains the main application service:
package internal
import (
"context"
"github.com/gofiber/fiber/v2"
"github.com/matzefriedrich/parsley-docs/examples/integrations/gofiber/internal/route_handlers"
"github.com/matzefriedrich/parsley/pkg/bootstrap"
)
type parsleyApplication struct {
app *fiber.App
}
var _ bootstrap.Application = &parsleyApplication{}
// NewApp Creates the main application service instance. This constructor function gets invoked by Parsley; add parameters for all required services.
func NewApp(app *fiber.App, routeHandlers []route_handlers.RouteHandler) bootstrap.Application {
for _, routeHandler := range routeHandlers {
routeHandler.Register(app)
}
return &parsleyApplication{
app: app,
}
}
// Run The entrypoint for the Parsley application.
func (a *parsleyApplication) Run(_ context.Context) error {
return a.app.Listen(":5502")
}
This file defines the parsleyApplication
struct as the main application service. It registers the route handlers and starts the GoFiber server on port 5502
. However, aspects like having the listener port configurable or a graceful server shutdown are omitted here, but they could be addressed here as well.
#
Running the Application
To run the application, navigate to the root directory and execute the following command:
go run main.go
As configured in the code, the application will start a GoFiber server on http://localhost:5502
. You can then access the /say-hello
endpoint:
curl "http://localhost:5502/say-hello?name=John"
This should return:
Good day, John!
For more details on Parsley, check out the Parsley GitHub repository.