Skip to content

Commit 182c1a5

Browse files
authored
Merge pull request #3148 from SppamLite/openapi-recipe
Add OpenAPI recipe
2 parents 713bca7 + b93aa90 commit 182c1a5

File tree

10 files changed

+465
-1
lines changed

10 files changed

+465
-1
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ Here you can find the most **delicious** recipes to cook delicious meals using o
3232
- [Docker + MariaDB](./docker-mariadb-clean-arch/README.md) - Dockerized MariaDB with Clean Architecture.
3333
- [Docker + Nginx](./docker-nginx-loadbalancer/README.md) - Load balancing with Docker and Nginx.
3434
- [Dummy JSON Proxy](./dummyjson/README.md) - Proxying dummy JSON data.
35-
- [Email Verification](./email-verification/README.md) - Email verification service with code generation and validation.
35+
- [Email Verification Service](./email-verification/README.md) - Email verification service with code generation and validation
3636
- [Entgo ORM (MySQL)](./ent-mysql/README.md) - Using Entgo ORM with MySQL
3737
- [Entgo Sveltekit](./entgo-sveltekit/README.md) - A full-stack Todo application built using Sveltekit, Tailwind CSS, Entgo, and SQLite.
3838
- [Envoy External Authorization](./envoy-extauthz/README.md) - External authorization with Envoy.
@@ -66,6 +66,7 @@ Here you can find the most **delicious** recipes to cook delicious meals using o
6666
- [Neo4j](./neo4j/README.md) - Connecting to a Neo4j database.
6767
- [OAuth2](./oauth2/README.md) - Implementing OAuth2 authentication.
6868
- [Google OAuth2](./oauth2-google/README.md) - Implementing Google OAuth2 authentication.
69+
- [OpenAPI](./openapi/README.md) - Generate OpenAPI 3 documentation and JSON schema for your application.
6970
- [Optional Parameter](./optional-parameter/README.md) - Handling optional parameters.
7071
- [Parsley](./parsley/README.md) - Using Parsley for dependency injection in an application.
7172
- [PostgreSQL](./postgresql/README.md) - Connecting to a PostgreSQL database.

openapi/.env

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
DB_USER=
2+
DB_PASSWORD=
3+
DB_HOST=
4+
DB_NAME=
5+
DB_PORT=

openapi/README.md

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
---
2+
title: OpenAPI
3+
keywords: [openAPI, api, documentation, huma]
4+
description: Generate OpenAPI 3 documentation and JSON schema for your application.
5+
---
6+
7+
# OpenAPI Documentation
8+
9+
[![Github](https://img.shields.io/static/v1?label=&message=Github&color=2ea44f&style=for-the-badge&logo=github)](https://github.com/gofiber/recipes/tree/master/openapi) [![StackBlitz](https://img.shields.io/static/v1?label=&message=StackBlitz&color=2ea44f&style=for-the-badge&logo=StackBlitz)](https://stackblitz.com/github/gofiber/recipes/tree/master/openapi)
10+
11+
This project demonstrates how to add OpenAPI 3 documentation to a Go application using [Huma](https://github.com/danielgtaylor/huma).
12+
13+
This project got inspired by the [swagger recipe](https://github.com/gofiber/recipes/tree/master/swagger).
14+
15+
## Prerequisites
16+
17+
Ensure you have the following installed:
18+
19+
- Golang
20+
21+
## Setup
22+
23+
1. Clone the repository:
24+
25+
```sh
26+
git clone https://github.com/gofiber/recipes.git
27+
cd recipes/openapi
28+
```
29+
30+
2. Download Go modules:
31+
```sh
32+
go mod tidy
33+
```
34+
35+
## Running the Application
36+
37+
1. Start the application:
38+
39+
```sh
40+
go run main.go
41+
```
42+
43+
2. Access the API Documentation:
44+
Open your browser and navigate to `http://localhost:3000/docs`.
45+
46+
3. OpenAPI Specs:
47+
- OpenAPI 3.1 JSON: `http://localhost:3000/openapi.json`.
48+
- OpenAPI 3.1 YAML: `http://localhost:3000/openapi.yaml`.
49+
- OpenAPI 3.0.3 JSON: `http://localhost:3000/openapi-3.0.json`.
50+
- OpenAPI 3.0.3 YAML: `http://localhost:3000/openapi-3.0.yaml`.
51+
52+
4. Generating TypeScript schema:
53+
54+
```sh
55+
npx openapi-typescript http://localhost:3000/openapi.json -o schema.ts
56+
```
57+
58+
## Example
59+
60+
Here is a minimal example of adding huma to a existing Fiber codebase:
61+
62+
### `routes.go`
63+
64+
```go
65+
import (
66+
...
67+
"github.com/gofiber/fiber/v2"
68+
"github.com/danielgtaylor/huma/v2"
69+
"github.com/danielgtaylor/huma/v2/adapters/humafiber"
70+
)
71+
func New() *fiber.App {
72+
app := fiber.New()
73+
api := humafiber.New(app, huma.DefaultConfig("Book API", "1.0.0"))
74+
75+
// app.Get("/books", handlers.GetAllBooks) // 👈 your existing code
76+
huma.Get(api, "/books", handlers.GetAllBooks) // 👈 huma version
77+
return app
78+
}
79+
```
80+
81+
### `handlers/book.go`
82+
83+
```go
84+
// func GetAllBooks(c *fiber.Ctx) error {} // 👈 your existing code
85+
86+
// 👇 huma version
87+
func GetAllBooks(ctx context.Context, _ *struct{}) (*GetAllBooksResponse, error) {
88+
return &GetAllBooksResponse{Body: books}, nil
89+
}
90+
```
91+
92+
## Enhancing Documentation
93+
94+
You can use `huma.Register` to add more information to the OpenAPI specification, such as descriptions with Markdown, examples, tags, and more.
95+
96+
```go
97+
// huma.Get(group, "/books/{id}", handlers.GetBookByID)
98+
99+
huma.Register(api, huma.Operation{
100+
OperationID: "get-book-by-id",
101+
Method: http.MethodGet,
102+
Path: "/book/{id}",
103+
Summary: "Get a book",
104+
Description: "Get a book by book ID.",
105+
Tags: []string{"Books"},
106+
}, handlers.GetBookByID)
107+
```
108+
109+
## References
110+
111+
- [Huma Documentation](https://github.com/danielgtaylor/huma)
112+
- [Huma Fiber Adapter](https://huma.rocks/features/bring-your-own-router)
113+
- [Enhancing Documentation](https://huma.rocks/tutorial/your-first-api/#enhancing-documentation)

openapi/database/connection.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package database
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"strconv"
7+
"time"
8+
9+
"gorm.io/driver/postgres"
10+
"gorm.io/gorm"
11+
)
12+
13+
var (
14+
// DBConn is a pointer to gorm.DB
15+
DBConn *gorm.DB
16+
user = os.Getenv("DB_USER")
17+
password = os.Getenv("DB_PASSWORD")
18+
host = os.Getenv("DB_HOST")
19+
db = os.Getenv("DB_NAME")
20+
port = os.Getenv("DB_PORT")
21+
)
22+
23+
// Connect creates a connection to database
24+
func Connect() (err error) {
25+
portInt, err := strconv.Atoi(port)
26+
if err != nil {
27+
return err
28+
}
29+
30+
dsn := fmt.Sprintf("user=%s password=%s host=%s dbname=%s port=%d sslmode=disable", user, password, host, db, portInt)
31+
DBConn, err = gorm.Open(postgres.Open(dsn), &gorm.Config{})
32+
if err != nil {
33+
return err
34+
}
35+
36+
sqlDB, err := DBConn.DB()
37+
if err != nil {
38+
return err
39+
}
40+
41+
sqlDB.SetMaxIdleConns(10)
42+
sqlDB.SetMaxOpenConns(50)
43+
sqlDB.SetConnMaxLifetime(time.Hour)
44+
45+
return nil
46+
}

openapi/go.mod

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
module openapi
2+
3+
go 1.24.1
4+
5+
require (
6+
github.com/danielgtaylor/huma/v2 v2.32.0
7+
github.com/gofiber/fiber/v2 v2.52.8
8+
github.com/joho/godotenv v1.5.1
9+
gorm.io/driver/postgres v1.6.0
10+
gorm.io/gorm v1.30.0
11+
)
12+
13+
require (
14+
github.com/andybalholm/brotli v1.1.1 // indirect
15+
github.com/google/uuid v1.6.0 // indirect
16+
github.com/jackc/pgpassfile v1.0.0 // indirect
17+
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
18+
github.com/jackc/pgx/v5 v5.6.0 // indirect
19+
github.com/jackc/puddle/v2 v2.2.2 // indirect
20+
github.com/jinzhu/inflection v1.0.0 // indirect
21+
github.com/jinzhu/now v1.1.5 // indirect
22+
github.com/klauspost/compress v1.18.0 // indirect
23+
github.com/mattn/go-colorable v0.1.13 // indirect
24+
github.com/mattn/go-isatty v0.0.20 // indirect
25+
github.com/mattn/go-runewidth v0.0.16 // indirect
26+
github.com/rivo/uniseg v0.4.7 // indirect
27+
github.com/stretchr/testify v1.10.0 // indirect
28+
github.com/valyala/bytebufferpool v1.0.0 // indirect
29+
github.com/valyala/fasthttp v1.62.0 // indirect
30+
golang.org/x/crypto v0.38.0 // indirect
31+
golang.org/x/sync v0.14.0 // indirect
32+
golang.org/x/sys v0.33.0 // indirect
33+
golang.org/x/text v0.25.0 // indirect
34+
)

openapi/go.sum

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA=
2+
github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA=
3+
github.com/danielgtaylor/huma/v2 v2.32.0 h1:ytU9ExG/axC434+soXxwNzv0uaxOb3cyCgjj8y3PmBE=
4+
github.com/danielgtaylor/huma/v2 v2.32.0/go.mod h1:9BxJwkeoPPDEJ2Bg4yPwL1mM1rYpAwCAWFKoo723spk=
5+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
6+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
7+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
8+
github.com/gofiber/fiber/v2 v2.52.8 h1:xl4jJQ0BV5EJTA2aWiKw/VddRpHrKeZLF0QPUxqn0x4=
9+
github.com/gofiber/fiber/v2 v2.52.8/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
10+
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
11+
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
12+
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
13+
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
14+
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
15+
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
16+
github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY=
17+
github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw=
18+
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
19+
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
20+
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
21+
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
22+
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
23+
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
24+
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
25+
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
26+
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
27+
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
28+
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
29+
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
30+
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
31+
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
32+
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
33+
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
34+
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
35+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
36+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
37+
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
38+
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
39+
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
40+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
41+
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
42+
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
43+
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
44+
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
45+
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
46+
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
47+
github.com/valyala/fasthttp v1.62.0 h1:8dKRBX/y2rCzyc6903Zu1+3qN0H/d2MsxPPmVNamiH0=
48+
github.com/valyala/fasthttp v1.62.0/go.mod h1:FCINgr4GKdKqV8Q0xv8b+UxPV+H/O5nNFo3D+r54Htg=
49+
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
50+
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
51+
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
52+
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
53+
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
54+
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
55+
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
56+
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
57+
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
58+
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
59+
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
60+
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
61+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
62+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
63+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
64+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
65+
gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4=
66+
gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
67+
gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs=
68+
gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=

0 commit comments

Comments
 (0)