@@ -1233,157 +1233,87 @@ func TestDefaultHTTPErrorHandler_CommitedResponse(t *testing.T) {
12331233 assert .Equal (t , http .StatusOK , resp .Code )
12341234}
12351235
1236- func TestAutoHeadRoute (t * testing.T ) {
1236+ func TestRouterAutoHandleHEADFullHTTPHandlerFlow (t * testing.T ) {
12371237 tests := []struct {
1238- name string
1239- autoHead bool
1240- method string
1241- wantBody bool
1242- wantCode int
1243- wantCLen bool // expect Content-Length header
1238+ name string
1239+ givenAutoHandleHEAD bool
1240+ whenMethod string
1241+ expectBody string
1242+ expectCode int
1243+ expectContentLength string
12441244 }{
12451245 {
1246- name : "AutoHead disabled - HEAD returns 405" ,
1247- autoHead : false ,
1248- method : http .MethodHead ,
1249- wantCode : http .StatusMethodNotAllowed ,
1250- wantBody : false ,
1246+ name : "AutoHandleHEAD disabled - HEAD returns 405" ,
1247+ givenAutoHandleHEAD : false ,
1248+ whenMethod : http .MethodHead ,
1249+ expectCode : http .StatusMethodNotAllowed ,
1250+ expectBody : "" ,
12511251 },
12521252 {
1253- name : "AutoHead enabled - HEAD returns 200 with Content-Length" ,
1254- autoHead : true ,
1255- method : http .MethodHead ,
1256- wantCode : http .StatusOK ,
1257- wantBody : false ,
1258- wantCLen : true ,
1253+ name : "AutoHandleHEAD enabled - HEAD returns 200 with Content-Length" ,
1254+ givenAutoHandleHEAD : true ,
1255+ whenMethod : http .MethodHead ,
1256+ expectCode : http .StatusOK ,
1257+ expectBody : "" ,
1258+ expectContentLength : "4" ,
12591259 },
12601260 {
1261- name : "GET request works normally with AutoHead enabled" ,
1262- autoHead : true ,
1263- method : http .MethodGet ,
1264- wantCode : http .StatusOK ,
1265- wantBody : true ,
1261+ name : "GET request works normally with AutoHandleHEAD enabled" ,
1262+ givenAutoHandleHEAD : true ,
1263+ whenMethod : http .MethodGet ,
1264+ expectCode : http .StatusOK ,
1265+ expectBody : "test" ,
12661266 },
12671267 }
12681268
1269- for _ , tt := range tests {
1270- t .Run (tt .name , func (t * testing.T ) {
1271- // Create Echo instance with AutoHead configuration
1272- e := New ()
1273- e .AutoHead = tt .autoHead
1269+ for _ , tc := range tests {
1270+ t .Run (tc .name , func (t * testing.T ) {
1271+ e := NewWithConfig (Config {
1272+ Router : NewRouter (RouterConfig {
1273+ AutoHandleHEAD : tc .givenAutoHandleHEAD ,
1274+ }),
1275+ })
12741276
1275- // Register a simple GET route
1276- testBody := "Hello, World!"
12771277 e .GET ("/hello" , func (c * Context ) error {
1278- return c .String (http .StatusOK , testBody )
1278+ return c .String (http .StatusOK , "test" )
12791279 })
12801280
1281- // Create request and response
1282- req := httptest .NewRequest (tt .method , "/hello" , nil )
1281+ req := httptest .NewRequest (tc .whenMethod , "/hello" , nil )
12831282 rec := httptest .NewRecorder ()
12841283
1285- // Serve the request
12861284 e .ServeHTTP (rec , req )
12871285
1288- // Verify status code
1289- if rec .Code != tt .wantCode {
1290- t .Errorf ("expected status %d, got %d" , tt .wantCode , rec .Code )
1291- }
1292-
1293- // Verify response body
1294- if tt .wantBody {
1295- if rec .Body .String () != testBody {
1296- t .Errorf ("expected body %q, got %q" , testBody , rec .Body .String ())
1297- }
1298- } else {
1299- if rec .Body .String () != "" {
1300- t .Errorf ("expected empty body for HEAD, got %q" , rec .Body .String ())
1301- }
1302- }
1303-
1304- // Verify Content-Length header for HEAD
1305- if tt .wantCLen && tt .method == http .MethodHead {
1306- clen := rec .Header ().Get ("Content-Length" )
1307- if clen == "" {
1308- t .Error ("expected Content-Length header for HEAD request" )
1309- }
1310- }
1286+ assert .Equal (t , tc .expectCode , rec .Code )
1287+ assert .Equal (t , tc .expectContentLength , rec .Header ().Get (HeaderContentLength ))
1288+ assert .Equal (t , tc .expectBody , rec .Body .String ())
13111289 })
13121290 }
13131291}
13141292
13151293func TestAutoHeadExplicitHeadTakesPrecedence (t * testing.T ) {
1316- e := New ()
1317- e .AutoHead = true
1294+ e := NewWithConfig (Config {
1295+ Router : NewRouter (RouterConfig {
1296+ AutoHandleHEAD : true ,
1297+ }),
1298+ })
13181299
13191300 // Register explicit HEAD route FIRST with custom behavior
13201301 e .HEAD ("/api/users" , func (c * Context ) error {
13211302 c .Response ().Header ().Set ("X-Custom-Header" , "explicit-head" )
1322- return c .NoContent (http .StatusOK )
1303+ return c .NoContent (http .StatusTeapot )
13231304 })
13241305
1325- // Then register GET route - AutoHead will try to add a HEAD route but fail silently
1326- // since one already exists
13271306 e .GET ("/api/users" , func (c * Context ) error {
1328- return c .JSON (http .StatusOK , map [string ]string {"name" : "John" })
1307+ return c .JSON (http .StatusNotFound , map [string ]string {"name" : "John" })
13291308 })
13301309
1331- // Test that the explicit HEAD route behavior is preserved
13321310 req := httptest .NewRequest (http .MethodHead , "/api/users" , nil )
13331311 rec := httptest .NewRecorder ()
13341312 e .ServeHTTP (rec , req )
13351313
1336- if rec .Code != http .StatusOK {
1337- t .Errorf ("expected status 200, got %d" , rec .Code )
1338- }
1339-
1340- if rec .Header ().Get ("X-Custom-Header" ) != "explicit-head" {
1341- t .Error ("expected explicit HEAD route to be used" )
1342- }
1343-
1344- // Verify body is empty
1345- if rec .Body .String () != "" {
1346- t .Errorf ("expected empty body for HEAD, got %q" , rec .Body .String ())
1347- }
1348- }
1349-
1350- func TestAutoHeadWithMiddleware (t * testing.T ) {
1351- e := New ()
1352- e .AutoHead = true
1353-
1354- // Add request logger middleware
1355- middlewareExecuted := false
1356- e .Use (func (next HandlerFunc ) HandlerFunc {
1357- return func (c * Context ) error {
1358- middlewareExecuted = true
1359- c .Response ().Header ().Set ("X-Middleware" , "executed" )
1360- return next (c )
1361- }
1362- })
1363-
1364- // Register GET route
1365- e .GET ("/test" , func (c * Context ) error {
1366- return c .String (http .StatusOK , "test response" )
1367- })
1368-
1369- // Test HEAD request goes through middleware
1370- req := httptest .NewRequest (http .MethodHead , "/test" , nil )
1371- rec := httptest .NewRecorder ()
1372-
1373- middlewareExecuted = false
1374- e .ServeHTTP (rec , req )
1375-
1376- if ! middlewareExecuted {
1377- t .Error ("middleware should execute for automatic HEAD route" )
1378- }
1379-
1380- if rec .Header ().Get ("X-Middleware" ) != "executed" {
1381- t .Error ("middleware header not set" )
1382- }
1383-
1384- if rec .Body .String () != "" {
1385- t .Errorf ("expected empty body for HEAD, got %q" , rec .Body .String ())
1386- }
1314+ assert .Equal (t , http .StatusTeapot , rec .Code )
1315+ assert .Equal (t , "explicit-head" , rec .Header ().Get ("X-Custom-Header" ))
1316+ assert .Equal (t , "" , rec .Body .String ())
13871317}
13881318
13891319func benchmarkEchoRoutes (b * testing.B , routes []testRoute ) {
@@ -1431,23 +1361,3 @@ func BenchmarkEchoGitHubAPIMisses(b *testing.B) {
14311361func BenchmarkEchoParseAPI (b * testing.B ) {
14321362 benchmarkEchoRoutes (b , parseAPI )
14331363}
1434-
1435- func BenchmarkAutoHeadRoute (b * testing.B ) {
1436- e := New ()
1437- e .AutoHead = true
1438-
1439- e .GET ("/bench" , func (c * Context ) error {
1440- return c .String (http .StatusOK , "benchmark response body" )
1441- })
1442-
1443- req := httptest .NewRequest (http .MethodHead , "/bench" , nil )
1444- rec := httptest .NewRecorder ()
1445-
1446- b .ReportAllocs ()
1447- b .ResetTimer ()
1448-
1449- for i := 0 ; i < b .N ; i ++ {
1450- rec .Body .Reset ()
1451- e .ServeHTTP (rec , req )
1452- }
1453- }
0 commit comments