Skip to content

Commit aef6766

Browse files
1 parent e75e129 commit aef6766

File tree

1 file changed

+200
-16
lines changed

1 file changed

+200
-16
lines changed

docs/recipes/parsley/README.md

Lines changed: 200 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,31 +10,215 @@ description: Using Parsley for dependency injection in an application.
1010

1111
This example demonstrates integrating the [Parsley dependency injection framework](https://github.com/matzefriedrich/parsley) into a GoFiber web application. The goal is to showcase how dependency injection can create a clean, maintainable, and modular structure in your GoFiber projects.
1212

13+
14+
## Prerequisites
15+
16+
* Go 1.23+
17+
18+
1319
## Overview
1420

15-
In this example, we use Parsley to:
21+
In this example, we use [Parsley](https://github.com/matzefriedrich/parsley) to:
22+
23+
* **Bootstrap the application:** Set up and configure the Fiber app using Parsley’s DI container.
24+
* **Register dependencies:** Define and register services and route handlers with the DI container.
25+
* **Resolve dependencies:** Automatically resolve and inject them where needed.
1626

17-
* **Bootstrap the Application:** Set up and configure the Fiber app using Parsley’s DI container.
18-
* **Register Dependencies:** Define and register services and route handlers with the DI container.
19-
* **Resolve Dependencies:** Automatically resolve and inject them where needed.
2027

21-
## Key Features
28+
### Key features
2229

23-
* **Modular Configuration:** Services are registered in modules, allowing for a clean separation of concerns.
24-
* **Automatic Dependency Injection:** Constructor-based dependency injection wire services together.
25-
* **Simplified Route Management:** Route handlers are registered and managed via the DI container, making it easy to extend and maintain.
30+
* **Modular configuration:** Services are registered in modules, allowing for a clean separation of concerns.
31+
* **Automatic dependency injection:** Constructor-based dependency injection wires services together.
32+
* **Simplified route management:** Route handlers are registered and managed via the DI container, making it easy to extend and maintain.
2633

27-
## How It Works
34+
35+
## How it works
2836

2937
* The `main` function bootstraps the application using Parsley’s `RunParsleyApplication` function.
3038
* Modules define how services (such as the Fiber app and route handlers) are registered and configured.
31-
* Route handlers are implemented as services that receive their dependencies (like the `Greeter` service) via constructor injection.
32-
The `Greeter` service is a simple example of how services can be injected and used within route handlers to handle HTTP requests.
39+
* Route handlers are implemented as services that receive their dependencies (like the `Greeter` service) via constructor injection. The `Greeter` service is a simple example of how services can be injected and used within route handlers to handle requests.
40+
41+
42+
## The recipe - step by step
43+
44+
This guide demonstrates integrating the Parsley dependency injection framework with the GoFiber web framework. You can either clone the GoFiber recipes repository and navigate to the **parsley** example, or replicate each module while following the article:
45+
46+
```sh
47+
git clone https://github.com/gofiber/recipes.git
48+
cd recipes/parsley
49+
```
50+
51+
The main entry point of the application is in the `cmd/main.go`.
52+
53+
```go
54+
package main
55+
56+
import (
57+
"context"
58+
59+
"github.com/gofiber/recipes/parsley-app/internal"
60+
"github.com/gofiber/recipes/parsley-app/internal/modules"
61+
62+
"github.com/matzefriedrich/parsley/pkg/bootstrap"
63+
)
64+
65+
func main() {
66+
67+
ctx := context.Background()
68+
69+
// Runs a Fiber instance as a Parsley-enabled app
70+
bootstrap.RunParsleyApplication(ctx, internal.NewApp,
71+
modules.ConfigureFiber,
72+
modules.ConfigureGreeter)
73+
}
74+
```
75+
76+
In this file, the `RunParsleyApplication` function bootstraps the application. It initializes the Parsley application context and configures the GoFiber server with the necessary services and route handlers. Parsley's `bootstrap` package is generic and could also be used with other web application frameworks; the glue is the `NewApp` method, representing a constructor function that must return a `bootstrap.Application` instance.
77+
78+
The last parameter of the `RunParsleyApplication` function is an ellipsis parameter accepting `ModuleFunc` values representing service registration functions, which are invoked before calling the constructor function for `bootstrap.Application`. Here, the `ConfigureFiber` and `ConfigureGreeter` functions are specified; those are defined by the `modules` package.
79+
80+
81+
### Configure and register the Fiber instance
82+
83+
The `ConfigureFiber` function sets up the Fiber application and registers it as a singleton service within the Parsley framework:
84+
85+
```go
86+
package modules
87+
88+
import (
89+
"github.com/gofiber/fiber/v2"
90+
"github.com/matzefriedrich/parsley/pkg/registration"
91+
"github.com/matzefriedrich/parsley/pkg/types"
92+
)
93+
94+
var _ types.ModuleFunc = ConfigureFiber
95+
96+
func ConfigureFiber(registry types.ServiceRegistry) error {
97+
registration.RegisterInstance(registry, fiber.Config{
98+
AppName: "parsley-app-recipe",
99+
Immutable: true,
100+
})
101+
102+
registry.Register(newFiber, types.LifetimeSingleton)
103+
registry.RegisterModule(RegisterRouteHandlers)
104+
105+
return nil
106+
}
107+
108+
func newFiber(config fiber.Config) *fiber.App {
109+
return fiber.New(config)
110+
}
111+
112+
```
113+
114+
This configuration ensures that the Fiber instance is initialized and available for dependency injection.
115+
116+
117+
### Define and register the application service(s)
118+
119+
The `Greeter` service generates greeting messages based on input parameters. In the recipe example application, this service is a dependency required by the handler of the `say-hello` route.
120+
121+
```go
122+
package services
123+
124+
import "fmt"
125+
126+
type Greeter interface {
127+
SayHello(name string, polite bool) string
128+
}
129+
130+
type greeter struct{}
131+
132+
func (g *greeter) SayHello(name string, polite bool) string {
133+
if polite {
134+
return fmt.Sprintf("Good day, %s!\n", name)
135+
}
136+
return fmt.Sprintf("Hi, %s\n", name)
137+
}
138+
139+
func NewGreeter() Greeter {
140+
return &greeter{}
141+
}
142+
```
143+
144+
The `Greeter` service is registered by the `ConfigureGreeter` service registration module:
145+
146+
```go
147+
package modules
148+
149+
import (
150+
"github.com/gofiber/recipes/parsley-app/internal/services"
151+
152+
"github.com/matzefriedrich/parsley/pkg/types"
153+
)
154+
155+
func ConfigureGreeter(registry types.ServiceRegistry) error {
156+
registry.Register(services.NewGreeterFactory, types.LifetimeTransient)
157+
return nil
158+
}
159+
```
160+
161+
This setup allows the `Greeter` service to be injected wherever needed within the application.
162+
163+
164+
### Implement and register route handlers
165+
166+
Route handlers in this example are services that implement the `RouteHandler` interface, allowing them to register routes with the Fiber application.
167+
168+
```go
169+
package route_handlers
170+
171+
import (
172+
"strconv"
173+
174+
"github.com/gofiber/recipes/parsley-app/internal/services"
175+
176+
"github.com/gofiber/fiber/v2"
177+
)
178+
179+
type greeterRouteHandler struct {
180+
greeter services.Greeter
181+
}
182+
183+
const defaultPoliteFlag = "true"
184+
185+
func (h *greeterRouteHandler) Register(app *fiber.App) {
186+
app.Get("/say-hello", h.HandleSayHelloRequest)
187+
}
188+
189+
func (h *greeterRouteHandler) HandleSayHelloRequest(ctx *fiber.Ctx) error {
190+
191+
name := ctx.Query("name")
192+
193+
politeFlag := ctx.Query("polite", defaultPoliteFlag)
194+
polite, _ := strconv.ParseBool(politeFlag)
195+
196+
msg := h.greeter.SayHello(name, polite)
197+
return ctx.Status(fiber.StatusOK).Send([]byte(msg))
198+
}
199+
200+
var _ RouteHandler = &greeterRouteHandler{}
201+
202+
func NewGreeterRouteHandler(greeter services.Greeter) RouteHandler {
203+
return &greeterRouteHandler{
204+
greeter: greeter,
205+
}
206+
}
207+
```
208+
209+
This handler responds to GET requests at `/say-hello` with a greeting message, utilizing the `Greeter` service injected via the constructor function.
210+
211+
212+
## Run the application
213+
214+
To start the application, execute:
33215

34-
## Running the Example
216+
```sh
217+
go run ./cmd/main.go
218+
```
35219

36-
To run this example:
220+
Once running, you can test the `say-hello` endpoint via the browser, or from the terminal using `curl`. For this recipe, the default listening port is `5502`:
37221

38-
* Clone the repository and navigate to the example directory.
39-
* Run `go run main.go` to start the application.
40-
* Access the application by navigating to `http://localhost:5502/say-hello?name=YourName`. This will return a greeting message, demonstrating the integration of Parsley with GoFiber.
222+
```sh
223+
curl http://localhost:5502/say-hello?name=YourName&polite=true
224+
```

0 commit comments

Comments
 (0)