-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathroute_doc.go
More file actions
138 lines (118 loc) · 4.15 KB
/
route_doc.go
File metadata and controls
138 lines (118 loc) · 4.15 KB
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
package hx
import (
"strings"
)
// Documented is implemented by handler types that self-describe their API contract.
// When a handler passed to Handle implements Documented, hx extracts the RouteDoc
// automatically — no separate hx.Doc call is needed at the registration site.
//
// This is the preferred pattern for production handlers: the documentation lives
// alongside the handler logic and travels with it through refactors.
//
// Example:
//
// type CreateOrderHandler struct {
// svc OrderService
// }
//
// func (h CreateOrderHandler) ServeHX(ctx context.Context, r *http.Request) error {
// // handler logic
// }
//
// func (h CreateOrderHandler) Doc() hx.RouteDoc {
// return hx.RouteDoc{
// Summary: "Create a new order",
// Tags: []string{"orders"},
// Request: CreateOrderRequest{},
// Responses: map[int]any{
// http.StatusCreated: CreateOrderResponse{},
// },
// Errors: []int{http.StatusUnprocessableEntity, http.StatusUnauthorized},
// }
// }
//
// server.Handle("POST /orders", CreateOrderHandler{svc}, authMiddleware)
type Documented interface {
Doc() RouteDoc
}
// RouteOpt is implemented by Middleware and Doc.
// Pass one or more RouteOpts to HandleFunc to configure a route.
type RouteOpt interface {
routeOpt()
}
// RouteDoc describes an HTTP operation for API documentation and spec generation.
type RouteDoc struct {
// Request is a zero-value of the request struct.
// Struct tags drive parameter and body extraction:
// json: request body field
// path: path parameter
// query: query parameter
// header: header parameter
// cookie: cookie parameter
// validate: constraints (required, min, max, enum, ...)
Request any
// Response is a zero-value of the primary success response body (200 OK).
Response any
// Responses document additional status codes and their response body types.
// Takes precedence over Response for the same status code.
// Use nil as the value to document a no-body response (e.g. 204).
// map[int]any{
// http.StatusCreated: OrderResponse{},
// http.StatusNoContent: nil,
// }
Responses map[int]any
// Errors list extra HTTP status codes this route returns as ProblemDetails.
// 400 and 500 are implicitly included on all routes.
// Only declare route-specific ones: 404, 409, 422, etc.
Errors []int
// Tags group this operation in the generated spec (e.g. "orders", "users").
Tags []string
// Summary is a short one-line description shown in tooling.
Summary string
// Description is a longer explanation. Markdown supported.
Description string
// OperationID is a unique identifier for code generators.
// Auto-derived from method + path if empty (e.g. "post_orders").
OperationID string
// Security references security scheme names defined at the server level.
// e.g. []string{"BearerAuth"}
Security []string
// Deprecated marks this operation as deprecated in the spec.
Deprecated bool
}
// docOpt wraps RouteDoc to implement RouteOpt.
type docOpt struct {
d RouteDoc
}
func (docOpt) routeOpt() {}
// Doc wraps a RouteDoc to be passed to HandleFunc alongside middlewares.
//
// server.HandleFunc("POST /orders", HandleCreateOrder(svc),
// hx.Doc(hx.RouteDoc{
// Request: CreateOrderRequest{},
// Response: OrderResponse{},
// Summary: "Create a new order",
// Tags: []string{"orders"},
// }),
// )
func Doc(d RouteDoc) RouteOpt {
return docOpt{d}
}
// RouteInfo is a registered route with its method, path, and optional documentation.
type RouteInfo struct {
Method string
Path string
Doc *RouteDoc
}
// Routes returns all routes registered on this server, including those registered via groups.
func (h *HX) Routes() []RouteInfo {
return *h.routes
}
// splitPattern splits a Go 1.22+ pattern like "POST /orders" into ("POST", "/orders").
// Returns ("*", pattern) for patterns without a method prefix (e.g. "/orders").
func splitPattern(pattern string) (method, path string) {
if i := strings.Index(pattern, " "); i != -1 {
return pattern[:i], pattern[i+1:]
}
return "*", pattern
}