@@ -14,10 +14,87 @@ import (
1414
1515 "github.com/danielgtaylor/huma/v2"
1616 "github.com/labstack/echo/v4"
17+ "github.com/stretchr/testify/assert"
1718)
1819
1920var lastModified = time .Now ()
2021
22+ // flushingResponseWriter simulates a ResponseWriter that flushes headers on WriteHeader.
23+ type flushingResponseWriter struct {
24+ rec * httptest.ResponseRecorder
25+ header http.Header
26+ wroteHeader bool
27+ }
28+
29+ func (m * flushingResponseWriter ) Header () http.Header {
30+ return m .header
31+ }
32+
33+ func (m * flushingResponseWriter ) WriteHeader (code int ) {
34+ if m .wroteHeader {
35+ return
36+ }
37+ m .wroteHeader = true
38+ // Write current headers to the recorder
39+ for k , v := range m .header {
40+ m .rec .Header ()[k ] = v
41+ }
42+ m .rec .WriteHeader (code )
43+ // Create a new header map so subsequent changes are NOT reflected in the recorder
44+ m .header = make (http.Header )
45+ }
46+
47+ func (m * flushingResponseWriter ) Write (b []byte ) (int , error ) {
48+ if ! m .wroteHeader {
49+ m .WriteHeader (http .StatusOK )
50+ }
51+ return m .rec .Write (b )
52+ }
53+
54+ func TestEchoLinkHeader (t * testing.T ) {
55+ e := echo .New ()
56+ conf := huma .DefaultConfig ("My API" , "1.0.0" )
57+ conf .SchemasPath = "/schemas"
58+ api := New (e , conf )
59+
60+ huma .Register (api , huma.Operation {
61+ Method : http .MethodGet ,
62+ Path : "/hello" ,
63+ OperationID : "get-hello" ,
64+ }, func (ctx context.Context , input * struct {}) (* struct {
65+ Body struct {
66+ Message string `json:"message"`
67+ }
68+ }, error ) {
69+ resp := & struct {
70+ Body struct {
71+ Message string `json:"message"`
72+ }
73+ }{}
74+ resp .Body .Message = "Hello"
75+ return resp , nil
76+ })
77+
78+ req , _ := http .NewRequest (http .MethodGet , "/hello" , nil )
79+ rec := httptest .NewRecorder ()
80+
81+ // Use our simulated flushing response writer to catch regression if
82+ // SetStatus is called before Transform.
83+ f := & flushingResponseWriter {
84+ rec : rec ,
85+ header : make (http.Header ),
86+ }
87+
88+ e .ServeHTTP (f , req )
89+
90+ assert .Equal (t , http .StatusOK , rec .Code )
91+
92+ // Check for Link header
93+ link := rec .Header ().Get ("Link" )
94+ assert .NotEmpty (t , link , "Link header should not be empty" )
95+ assert .Contains (t , link , "rel=\" describedBy\" " )
96+ }
97+
2198func BenchmarkHumaEcho (b * testing.B ) {
2299 type GreetingInput struct {
23100 ID string `path:"id"`
0 commit comments