Skip to content

Commit d485a12

Browse files
authored
Merge branch 'main' into fix-faulty-duplicate-detection
2 parents a142116 + 58edcf2 commit d485a12

38 files changed

Lines changed: 1773 additions & 452 deletions

.github/workflows/benchmark.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: Benchmark
2+
permissions:
3+
contents: read
4+
on:
5+
workflow_dispatch:
6+
jobs:
7+
benchmark:
8+
name: Performance regression check
9+
runs-on: ubuntu-latest
10+
if: github.event_name == 'workflow_dispatch'
11+
steps:
12+
- uses: actions/checkout@v4
13+
- name: Setup go
14+
uses: actions/setup-go@v5
15+
with:
16+
go-version: "1.25"
17+
- name: Run benchmark
18+
run: go test -bench=. -count=5 -benchmem ./... | tee output.txt
19+
- name: Download previous benchmark data
20+
uses: actions/cache@v4
21+
with:
22+
path: ./cache
23+
key: ${{ runner.os }}-benchmark-${{ github.sha }}
24+
restore-keys: |
25+
${{ runner.os }}-benchmark
26+
- name: Store benchmark result
27+
uses: benchmark-action/github-action-benchmark@v1
28+
with:
29+
tool: 'go'
30+
output-file-path: output.txt
31+
external-data-json-path: ./cache/benchmark-data.json
32+
fail-on-alert: true
33+
comment-on-alert: true
34+
github-token: ${{ secrets.GITHUB_TOKEN }}
35+
alert-threshold: '130%'
36+
comment-always: false

.github/workflows/ci.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ permissions:
33
contents: read
44
on:
55
push:
6-
branches: [main]
7-
pull_request: {}
6+
branches: [ main ]
7+
pull_request: { }
88
jobs:
99
build:
1010
runs-on: ubuntu-latest
1111
strategy:
1212
matrix:
13-
go: [1.24, 1.25]
13+
go: [ 1.25, 1.26 ]
1414
name: Build & Test
1515
steps:
1616
- uses: actions/checkout@v4
@@ -25,4 +25,4 @@ jobs:
2525
- run: go test -race -coverprofile=coverage.txt -covermode=atomic ./...
2626
- uses: codecov/codecov-action@v4
2727
with:
28-
token: ${{ secrets.CODECOV_TOKEN }}
28+
token: ${{ secrets.CODECOV_TOKEN }}

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ A big thank you to our current & former sponsors!
109109
110110
# Install
111111

112-
Install via `go get`. Note that Go 1.24 or newer is required.
112+
Install via `go get`. Note that Go 1.25 or newer is required.
113113

114114
```sh
115115
# After: go mod init ...
@@ -210,6 +210,10 @@ Official Go package documentation can always be found at https://pkg.go.dev/gith
210210
- [Bump.sh Deploying Docs from Huma](https://docs.bump.sh/guides/bump-sh-tutorials/huma/)
211211
- Mentioned in [Composable HTTP Handlers Using Generics](https://www.willem.dev/articles/generic-http-handlers/)
212212

213+
# Who is using Huma?
214+
215+
Huma is used by many companies and open-source projects. See the [Who is using Huma?](https://huma.rocks/why/#who-is-using-huma) page for a list!
216+
213217
Be sure to star the project if you find it useful!
214218

215219
<a href="https://star-history.com/#danielgtaylor/huma&Date">

README_CN.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
一个现代、简单、快速且灵活的微框架,用于在 OpenAPI 3 和 JSON Schema 支持的 Go 中构建 HTTP REST/RPC API。国际音标发音:[/'hjuːmɑ/](https://en.wiktionary.org/wiki/Wiktionary:International_Phonetic_Alphabet)。该项目的目标是提供:
2020

2121
- 拥有现有服务的团队逐步采用
22-
- 带上您自己的路由器(包括 Go 1.24+)、中间件和日志记录/指标
22+
- 带上您自己的路由器(包括 Go 1.22+)、中间件和日志记录/指标
2323
- 可扩展的 OpenAPI 和 JSON Schema 层来记录现有路由
2424
- 适合 Go 开发人员的现代 REST 或 HTTP RPC API 后端框架
2525
- [由OpenAPI 3.1](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md)[JSON Schema](https://json-schema.org/)描述
@@ -83,7 +83,7 @@
8383
8484
# 安装
8585

86-
通过安装`go get`。请注意,需要 Go 1.24 或更高版本。
86+
通过安装`go get`。请注意,需要 Go 1.25 或更高版本。
8787

8888
```sh
8989
# After: go mod init ...
@@ -150,7 +150,7 @@ func main() {
150150
```
151151

152152
> [!TIP]
153-
> 替换`chi.NewMux()``http.NewServeMux()``humachi.New``humago.New`以使用 Go 1.24+ 中的标准库路由器。只需确保其中列出了您的或更新的`go.mod`版本即可。`go 1.22`其他一切都保持不变!当你准备好时就切换。
153+
> 替换`chi.NewMux()``http.NewServeMux()``humachi.New``humago.New`以使用 Go 1.22+ 中的标准库路由器。只需确保其中列出了您的或更新的`go.mod`版本即可。`go 1.22`其他一切都保持不变!当你准备好时就切换。
154154
155155
你可以用 `go run greet.go` 测试它(可选地传递 '--port' 来更改默认值),并使用 [Restish](https://rest.sh/)(或 `curl`) 发出示例请求:
156156

@@ -184,6 +184,10 @@ HTTP/1.1 200 OK
184184
- [Bump.sh 从 Huma 部署文档](https://docs.bump.sh/guides/bump-sh-tutorials/huma/)
185185
- [使用泛型的可组合 HTTP 处理程序](https://www.willem.dev/articles/generic-http-handlers/)中提到
186186

187+
# 谁在使用 Huma?
188+
189+
Huma 被许多公司和开源项目所使用。请参阅 [谁在使用 Huma?](https://huma.rocks/why/#who-is-using-huma) 页面查看列表!
190+
187191
如果您觉得该项目有用,请务必为该项目加注星标!
188192

189193
<a href="https://star-history.com/#danielgtaylor/huma&Date">

README_JA.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
本プロジェクトの主な目的は以下の通りです:
3030

3131
- 既存サービスを持つチーム向けの段階的な導入
32-
- 好きなルーター(Go 1.24+対応含む)、ミドルウェア、ロギング/メトリクスを利用可能
32+
- 好きなルーター(Go 1.22+対応含む)、ミドルウェア、ロギング/メトリクスを利用可能
3333
- 既存ルートをドキュメント化できる拡張性の高いOpenAPI & JSON Schemaレイヤ
3434
- Go開発者のためのモダンなREST/HTTP RPC APIバックエンドフレームワーク
3535
- [OpenAPI 3.1](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md) & [JSON Schema](https://json-schema.org/)によるAPI記述
@@ -129,7 +129,7 @@
129129

130130
## インストール方法
131131

132-
`go get`でインストールできます。Go 1.24以降が必要です
132+
`go get`でインストールできます。Go 1.25以降が必要です
133133

134134
```sh
135135
# 事前に: go mod init ...
@@ -193,7 +193,7 @@ func main() {
193193
```
194194

195195
> **TIP:**
196-
> Go 1.24以降の標準ライブラリルーターを使う場合は`chi.NewMux()``http.NewServeMux()``humachi.New``humago.New`に変更してください。`go.mod``go`バージョンも1.22以上にする必要があります。それ以外は同じです。
196+
> Go 1.22 以降の標準ライブラリルーターを使う場合は`chi.NewMux()``http.NewServeMux()``humachi.New``humago.New`に変更してください。`go.mod``go`バージョンも1.22以上にする必要があります。それ以外は同じです。
197197
198198
サーバー起動例:
199199
`go run greet.go`(ポート指定は`--port`でも可)
@@ -235,6 +235,12 @@ HTTP/1.1 200 OK
235235

236236
---
237237

238+
## Humaを使用しているプロジェクト
239+
240+
Humaは多くの企業やオープンソースプロジェクトで使用されています。リストについては、[Humaを使用しているプロジェクト](https://huma.rocks/why/#who-is-using-huma)のページをご覧ください!
241+
242+
---
243+
238244
プロジェクトが役に立った場合はぜひスターをお願いします!
239245

240246
<a href="https://star-history.com/#danielgtaylor/huma&Date">

adapters/humafiber/humafiber.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ func (c *fiberWrapper) BodyReader() io.Reader {
107107
// Streaming is enabled, so send the reader.
108108
return orig.Request().BodyStream()
109109
}
110-
return bytes.NewReader(orig.BodyRaw())
110+
return bytes.NewReader(orig.Body())
111111
}
112112

113113
func (c *fiberWrapper) GetMultipartForm() (*multipart.Form, error) {

adapters/humafiber/humafiber_context_test.go

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,7 @@ func SimulateAccessToContextOutsideHandler(
118118
retries int,
119119
) func(ctx context.Context) {
120120
return func(ctx context.Context) {
121-
wait.Add(1)
122-
go func() {
123-
defer wait.Done()
121+
wait.Go(func() {
124122
global, cancel := context.WithTimeout(global, timeout*time.Duration(retries))
125123
defer cancel()
126124
for {
@@ -136,7 +134,7 @@ func SimulateAccessToContextOutsideHandler(
136134
case <-time.After(timeout / 10):
137135
}
138136
}
139-
}()
137+
})
140138
}
141139
}
142140

@@ -250,12 +248,10 @@ func TestHumaFiber(t *testing.T) {
250248
api.UseMiddleware(HumaMiddleware)
251249
huma.Register(api, HelloOperation(), HelloHandler(simulator))
252250

253-
wait.Add(1)
254-
go func() {
255-
defer wait.Done()
251+
wait.Go(func() {
256252
err := app.Listener(ln)
257253
assert.NoError(t, err)
258-
}()
254+
})
259255
defer wait.Wait()
260256

261257
err = WaitPing(ctx, server, timeout)
@@ -297,19 +293,17 @@ func TestHumaFiber(t *testing.T) {
297293

298294
// check that delay works
299295
doneFirst := make(chan bool)
300-
wait.Add(1)
301-
go func() {
302-
defer wait.Done()
296+
wait.Go(func() {
303297
defer close(doneFirst)
304298
response, err := http.DefaultClient.Do(request)
305299
if response != nil && response.Body != nil {
306300
defer func() {
307301
_ = response.Body.Close()
308302
}()
309303
}
310-
assert.NoError(t, err)
304+
require.NoError(t, err)
311305
HelloResponseValidate(t, expected, response)
312-
}()
306+
})
313307
select {
314308
case <-ctx.Done():
315309
return
@@ -329,31 +323,27 @@ func TestHumaFiber(t *testing.T) {
329323

330324
// check graceful shutdown
331325
doneSecond := make(chan bool)
332-
wait.Add(1)
333-
go func() {
334-
defer wait.Done()
326+
wait.Go(func() {
335327
defer close(doneSecond)
336328
response, err := http.DefaultClient.Do(request)
337329
if response != nil && response.Body != nil {
338330
defer func() {
339331
_ = response.Body.Close()
340332
}()
341333
}
342-
assert.NoError(t, err)
334+
require.NoError(t, err)
343335
HelloResponseValidate(t, expected, response)
344-
}()
336+
})
345337

346338
// perform shutdown
347339
doneShutdown := make(chan bool)
348-
wait.Add(1)
349-
go func() {
350-
defer wait.Done()
340+
wait.Go(func() {
351341
defer close(doneShutdown)
352342
time.Sleep(timeout) // delay before shutdown to start request processing
353343
err := app.ShutdownWithContext(ctx)
354-
assert.NoError(t, err)
344+
require.NoError(t, err)
355345
time.Sleep(timeout) // delay after shutdown to catch request processing
356-
}()
346+
})
357347

358348
// request should be handled
359349
select {

adapters/humamux/humamux.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,11 @@ func (c *gmuxContext) BodyWriter() io.Writer {
138138
return c.w
139139
}
140140

141+
// NewContext creates a new Huma context from an HTTP request and response.
142+
func NewContext(op *huma.Operation, r *http.Request, w http.ResponseWriter) huma.Context {
143+
return &gmuxContext{op: op, r: r, w: w}
144+
}
145+
141146
type gMux struct {
142147
options
143148
router *mux.Router
@@ -149,7 +154,7 @@ func (a *gMux) Handle(op *huma.Operation, handler func(huma.Context)) {
149154
Path(op.Path).
150155
Methods(op.Method).
151156
HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
152-
handler(&gmuxContext{op: op, r: r, w: w})
157+
handler(NewContext(op, r, w))
153158
})
154159
if a.routeCustomizer != nil {
155160
a.routeCustomizer(op, route)
@@ -160,6 +165,11 @@ func (a *gMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
160165
a.router.ServeHTTP(w, r)
161166
}
162167

168+
// NewAdapter creates a new adapter for the given Gorilla mux.
169+
func NewAdapter(r *mux.Router, options ...Option) huma.Adapter {
170+
return &gMux{router: r, options: parseOptions(options)}
171+
}
172+
163173
func New(r *mux.Router, config huma.Config, options ...Option) huma.API {
164-
return huma.NewAPI(config, &gMux{router: r, options: parseOptions(options)})
174+
return huma.NewAPI(config, NewAdapter(r, options...))
165175
}

0 commit comments

Comments
 (0)