-
-
Notifications
You must be signed in to change notification settings - Fork 150
/
humagin.go
138 lines (110 loc) · 3.01 KB
/
humagin.go
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 humagin
import (
"context"
"io"
"mime/multipart"
"net/http"
"net/url"
"strings"
"time"
"github.com/danielgtaylor/huma/v2"
"github.com/gin-gonic/gin"
)
// MultipartMaxMemory is the maximum memory to use when parsing multipart
// form data.
var MultipartMaxMemory int64 = 8 * 1024
type ginCtx struct {
op *huma.Operation
orig *gin.Context
status int
}
// check that ginCtx implements huma.Context
var _ huma.Context = &ginCtx{}
func (c *ginCtx) Operation() *huma.Operation {
return c.op
}
func (c *ginCtx) Context() context.Context {
return c.orig.Request.Context()
}
func (c *ginCtx) Method() string {
return c.orig.Request.Method
}
func (c *ginCtx) Host() string {
return c.orig.Request.Host
}
func (c *ginCtx) RemoteAddr() string {
return c.orig.Request.RemoteAddr
}
func (c *ginCtx) URL() url.URL {
return *c.orig.Request.URL
}
func (c *ginCtx) Param(name string) string {
return c.orig.Param(name)
}
func (c *ginCtx) Query(name string) string {
return c.orig.Query(name)
}
func (c *ginCtx) Header(name string) string {
return c.orig.GetHeader(name)
}
func (c *ginCtx) EachHeader(cb func(name, value string)) {
for name, values := range c.orig.Request.Header {
for _, value := range values {
cb(name, value)
}
}
}
func (c *ginCtx) BodyReader() io.Reader {
return c.orig.Request.Body
}
func (c *ginCtx) GetMultipartForm() (*multipart.Form, error) {
err := c.orig.Request.ParseMultipartForm(MultipartMaxMemory)
return c.orig.Request.MultipartForm, err
}
func (c *ginCtx) SetReadDeadline(deadline time.Time) error {
return huma.SetReadDeadline(c.orig.Writer, deadline)
}
func (c *ginCtx) SetStatus(code int) {
c.status = code
c.orig.Status(code)
}
func (c *ginCtx) Status() int {
return c.status
}
func (c *ginCtx) AppendHeader(name string, value string) {
c.orig.Writer.Header().Add(name, value)
}
func (c *ginCtx) SetHeader(name string, value string) {
c.orig.Header(name, value)
}
func (c *ginCtx) BodyWriter() io.Writer {
return c.orig.Writer
}
// Router is an interface that wraps the Gin router's Handle method.
type Router interface {
Handle(string, string, ...gin.HandlerFunc) gin.IRoutes
}
type ginAdapter struct {
http.Handler
router Router
}
func (a *ginAdapter) Handle(op *huma.Operation, handler func(huma.Context)) {
// Convert {param} to :param
path := op.Path
path = strings.ReplaceAll(path, "{", ":")
path = strings.ReplaceAll(path, "}", "")
a.router.Handle(op.Method, path, func(c *gin.Context) {
ctx := &ginCtx{op: op, orig: c}
handler(ctx)
})
}
func New(r *gin.Engine, config huma.Config) huma.API {
return huma.NewAPI(config, &ginAdapter{Handler: r, router: r})
}
// NewWithGroup creates a new Huma API using the provided Gin router and group,
// letting you mount the API at a sub-path. Can be used in combination with
// the `OpenAPI.Servers` field to set the correct base URL for the API / docs
// / schemas / etc.
func NewWithGroup(r *gin.Engine, g *gin.RouterGroup, config huma.Config) huma.API {
return huma.NewAPI(config, &ginAdapter{Handler: r, router: g})
}