hooks.go
1 package web 2 3 import ( 4 "fmt" 5 "net/http" 6 "net/http/httputil" 7 "net/url" 8 ) 9 10 func (t InternalRouter) hookHandler(w http.ResponseWriter, r *http.Request) { 11 var originIsPup bool = false 12 originIP := getOriginIP(r) 13 _, _, err := t.pm.FindPupByIP(originIP) 14 if err == nil { 15 originIsPup = true 16 } 17 18 if !originIsPup { 19 // you must be a pup! 20 forbidden(w, "You are not a Pup we know about", originIP) 21 return 22 } 23 24 hookID := r.PathValue("hookID") 25 handled := false 26 done: 27 for _, pup := range t.pm.GetStateMap() { 28 for _, hook := range pup.Hooks { 29 if hookID == hook.ID { 30 // check if the port is exposed first.. 31 exposed := false 32 for _, ex := range pup.Manifest.Container.Exposes { 33 if ex.Port == hook.Port { 34 exposed = true 35 } 36 } 37 if !exposed { 38 sendErrorResponse(w, http.StatusUnauthorized, "Proxy to unexposed port unsupported") 39 handled = true 40 break done 41 } 42 43 // proxy the request 44 targetURL, err := url.Parse(fmt.Sprintf("http://%s:%d%s", pup.IP, hook.Port, hook.Path)) 45 if err != nil { 46 sendErrorResponse(w, http.StatusInternalServerError, "couldn't compose proxy URL") 47 handled = true 48 break done 49 } 50 proxy := httputil.NewSingleHostReverseProxy(targetURL) 51 proxy.Director = func(req *http.Request) { 52 req.URL.Scheme = targetURL.Scheme 53 req.URL.Host = targetURL.Host 54 req.Header = r.Header 55 } 56 proxy.ServeHTTP(w, r) 57 58 handled = true 59 break done 60 } 61 } 62 } 63 64 if !handled { 65 sendErrorResponse(w, http.StatusNotFound, "Hook not found") 66 } 67 }