Frameworks
Route extraction per framework, and how to add your own.
Each framework registers routes differently, so endpoint detection is delegated to per-framework extractors. The built-ins are net/http, gin, echo, gRPC, GraphQL and ConnectRPC; each runs automatically (an extractor only fires on a package that uses its framework).
net/http
Detects mux.HandleFunc(pattern, handler) on *http.ServeMux and the
package-level http.HandleFunc. The Go 1.22+ method-prefixed pattern is parsed:
mux.HandleFunc("GET /catalog/items", h.ListItems) // method GET, path /catalog/itemsgin
Detects GET/POST/PUT/DELETE/PATCH/HEAD/OPTIONS, Handle, and Any on
*gin.Engine / *gin.RouterGroup:
r := gin.Default()
api := r.Group("/api")
api.GET("/users", userCtl.List) // handler resolves to (*UserController).ListAny HTTP router
Most Go routers share one shape — router.GET/Get/POST/...("/path", handler).
The generic router extractor matches it by the verb name, a string path, and a
function-typed handler argument, not by the router's concrete type, so gin,
echo, fiber, chi, httprouter and others are detected the same way. Group("/api")
prefixes are joined onto routes.
api := app.Group("/api") // gin r.Group, echo e.Group, fiber app.Group
api.Get("/users", h.List) // -> endpoint /api/usersecho
Detects GET/POST/... and Any on *echo.Echo / *echo.Group. The handler is
the argument right after the path; Group("/api") prefixes are joined onto the
route. Works with echo v3 and v4.
e := echo.New()
api := e.Group("/api")
api.GET("/users", userCtl.List) // endpoint /api/usersGraphQL
Detects gqlgen-style resolvers: an interface named
Query/Mutation/SubscriptionResolver implemented by a project type. Each
field becomes an endpoint bound to the resolver method.
type QueryResolver interface {
Order(ctx context.Context, id string) (*Order, error) // endpoint /Query/order
}Structural detection — no import required, so it works with real gqlgen output. Only root resolvers for now; nested field resolvers are on the roadmap.
gRPC
Detected structurally from the generated registration call — no import needed,
so it works with real google.golang.org/grpc as-is. Each RPC method on the
service interface becomes an endpoint bound to the implementing method:
pb.RegisterOrderServiceServer(grpcServer, &OrderServer{...})
// endpoints: /OrderService/CreateOrder, /OrderService/GetOrder, ...The server impl lives in a package classified as controller (e.g.
adapter/grpc), so the RPCs flow into your service and repository like any
other entry point.
ConnectRPC
Detects the generated New<Svc>Handler(impl) constructor (returns
(string, http.Handler)) from connectrpc.com/connect. Each RPC method on the
service handler interface becomes an endpoint — so a Connect service shows up
even though it doesn't use grpc-go's Register…Server.
Adding a framework
Implement the Extractor interface and pass it via Options.Extractors:
type Extractor interface {
Name() string
Match(pkg *packages.Package) bool // does this pkg import the framework?
Extract(pkg *packages.Package) []Route // walk syntax, return routes
}av, _ := archview.New(archview.Options{
Extractors: []archview.Extractor{myEchoExtractor{}, /* + defaults */},
})echo, fiber, chi, GraphQL and WebSocket adapters are on the roadmap. The interface is already in place — contributions welcome.