1 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 2 // use this file except in compliance with the License. You may obtain a copy of 3 // the License at 4 // 5 // http://www.apache.org/licenses/LICENSE-2.0 6 // 7 // Unless required by applicable law or agreed to in writing, software 8 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 // License for the specific language governing permissions and limitations under 11 // the License. 12 13 //go:build !js 14 15 package server 16 17 import ( 18 "io" 19 "net/http" 20 21 "github.com/go-chi/chi/v5" 22 ) 23 24 // GetHead automatically route undefined HEAD requests to GET handlers, and 25 // discards the response body for such requests. 26 // 27 // Forked from chi middleware package. 28 func GetHead(next http.Handler) http.Handler { 29 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 30 if r.Method == "HEAD" { 31 rctx := chi.RouteContext(r.Context()) 32 routePath := rctx.RoutePath 33 if routePath == "" { 34 if r.URL.RawPath != "" { 35 routePath = r.URL.RawPath 36 } else { 37 routePath = r.URL.Path 38 } 39 } 40 41 // Temporary routing context to look-ahead before routing the request 42 tctx := chi.NewRouteContext() 43 44 // Attempt to find a HEAD handler for the routing path, if not found, traverse 45 // the router as through its a GET route, but proceed with the request 46 // with the HEAD method. 47 if !rctx.Routes.Match(tctx, "HEAD", routePath) { 48 type httpWriter interface { // Just the methods unique to http.ResponseWriter 49 Header() http.Header 50 WriteHeader(statusCode int) 51 } 52 discardWriter := struct { 53 httpWriter 54 io.Writer 55 }{ 56 httpWriter: w, 57 Writer: io.Discard, 58 } 59 rctx.RouteMethod = "GET" 60 rctx.RoutePath = routePath 61 next.ServeHTTP(discardWriter, r) 62 return 63 } 64 } 65 66 next.ServeHTTP(w, r) 67 }) 68 } 69