1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169# fsrouter
A Go code generator that mirrors your `api/` filesystem into HTTP routes using [gorilla/mux](https://github.com/gorilla/mux).
## Installation
```bash
go install github.com/aquaticcalf/fsrouter@latest
```
## Usage
1. Structure your handlers under api/:
```
api/
users/ # First-level directory becomes route group
get.go # exports func Get(w http.ResponseWriter, r *http.Request)
[userId]/ # Dynamic parameter with [param] syntax
get.go # exports func Get(...)
post.go # exports func Post(...)
auth/ # Another route group
login/
post.go # exports func Post(...)
```
2. In your main.go, add:
```go
//go:generate fsrouter -api=./api -out=routes_gen.go -pkg=main -importPREFIX=yourmodule/api -middleware=yourmodule/middleware -middlewares="loggingMiddleware,authMiddleware,corsMiddleware" -groupMiddlewares='{"users":"authMiddleware","admin":"adminAuthMiddleware,loggingMiddleware"}' -notFound=customHandlers.NotFound
package main
import (
"log"
"net/http"
)
func main() {
r := RegisterRoutes() // generated
log.Fatal(http.ListenAndServe(":3000", r))
}
```
3. Generate and build:
```bash
go generate ./...
go build ./...
```
Routes will be wired up from `api/` files like `get.go`, `post.go`, etc.
## Features
- Automatic route registration from file system
- Dynamic parameters with `[param]` folder syntax
- Extensive Middleware Support
- Multiple global middlewares for all routes
- Group-specific middlewares for route groups
- Flexible configuration via command line flags
- Route grouping via first-level directories
- Each top-level directory becomes a subrouter
- Example: `/api/users/...` becomes a group
- Custom 404 handler support
- Specify with `-notFound=package.Handler`
- Default JSON 404 handler included
## Command Line Options
| Flag | Description | Default |
|------|-------------|---------|
| `-api` | Directory of API handlers | `api` |
| `-out` | Output file path | `routes_gen.go` |
| `-pkg` | Package name for generated file | `main` |
| `-importPREFIX` | Import path prefix for API handlers | (required) |
| `-middleware` | Package containing middleware functions | (optional) |
| `-middlewares` | Comma-separated list of middleware functions to apply globally | `loggingMiddleware` |
| `-groupMiddlewares` | JSON mapping of group to middleware list | (optional) |
| `-notFound` | Custom 404 handler (format: `package.Handler`) | (default handler used) |
## Setting Up Middleware
### Global Middleware
You can specify multiple global middlewares using the `-middlewares` flag:
```bash
fsrouter -middlewares="loggingMiddleware,authMiddleware,corsMiddleware"
```
### Group-Specific Middleware
There are two ways to set up group-specific middleware:
1. Using the `-groupMiddlewares` flag with a JSON string:
```bash
fsrouter -groupMiddlewares='{"users":"authMiddleware,rateLimit","admin":"adminAuthMiddleware"}'
```
2. Editing the generated code (will be overwritten on regeneration):
```go
// After generation, you can manually edit:
usersRouter.Use(authMiddleware)
adminRouter.Use(adminAuthMiddleware)
```
### Creating Custom Middleware
Define your middleware functions in your application code:
```go
// In your middleware package
func authMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Authentication logic here
token := r.Header.Get("Authorization")
if !validateToken(token) {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
next.ServeHTTP(w, r)
})
}
```
## Extending
The generated code can be further customized as needed, but keep in mind that regeneration will overwrite your changes.
Use the command-line flags whenever possible to avoid manual edits.
## Example Generated Router
```go
// Example for a simple API structure
func RegisterRoutes() *mux.Router {
r := mux.NewRouter()
// Global middleware
r.Use(loggingMiddleware)
r.Use(authMiddleware)
r.Use(corsMiddleware)
// Route groups
usersRouter := r.PathPrefix("/users").Subrouter()
usersRouter.Use(authMiddleware) // Group-specific middleware
adminRouter := r.PathPrefix("/admin").Subrouter()
adminRouter.Use(adminAuthMiddleware)
adminRouter.Use(loggingMiddleware)
authRouter := r.PathPrefix("/auth").Subrouter()
// Routes
usersRouter.HandleFunc("", users.Get).Methods("GET")
usersRouter.HandleFunc("/{userId}", users_userId.Get).Methods("GET")
adminRouter.HandleFunc("/dashboard", admin_dashboard.Get).Methods("GET")
authRouter.HandleFunc("/login", auth_login.Post).Methods("POST")
// 404 Handler
r.NotFoundHandler = http.HandlerFunc(defaultNotFoundHandler)
return r
}
```