@@ -26,11 +26,12 @@ import (
2626 "log"
2727 "net"
2828 "net/http"
29+ "net/http/httputil"
2930 "net/url"
3031 "time"
3132
3233 "github.com/gorilla/mux"
33- "github.com/openfaas/faas-provider/httputil"
34+ fhttputil "github.com/openfaas/faas-provider/httputil"
3435 "github.com/openfaas/faas-provider/types"
3536)
3637
@@ -68,6 +69,14 @@ func NewHandlerFunc(config types.FaaSConfig, resolver BaseURLResolver, verbose b
6869
6970 proxyClient := NewProxyClientFromConfig (config )
7071
72+ reverseProxy := httputil.ReverseProxy {}
73+ reverseProxy .Director = func (req * http.Request ) {
74+ // At least an empty director is required to prevent runtime errors.
75+ }
76+
77+ // Errors are common during disconnect of client, no need to log them.
78+ reverseProxy .ErrorLog = log .New (io .Discard , "" , 0 )
79+
7180 return func (w http.ResponseWriter , r * http.Request ) {
7281 if r .Body != nil {
7382 defer r .Body .Close ()
@@ -81,7 +90,7 @@ func NewHandlerFunc(config types.FaaSConfig, resolver BaseURLResolver, verbose b
8190 http .MethodGet ,
8291 http .MethodOptions ,
8392 http .MethodHead :
84- proxyRequest (w , r , proxyClient , resolver , verbose )
93+ proxyRequest (w , r , proxyClient , resolver , & reverseProxy , verbose )
8594
8695 default :
8796 w .WriteHeader (http .StatusMethodNotAllowed )
@@ -134,15 +143,15 @@ func NewProxyClient(timeout time.Duration, maxIdleConns int, maxIdleConnsPerHost
134143}
135144
136145// proxyRequest handles the actual resolution of and then request to the function service.
137- func proxyRequest (w http.ResponseWriter , originalReq * http.Request , proxyClient * http.Client , resolver BaseURLResolver , verbose bool ) {
146+ func proxyRequest (w http.ResponseWriter , originalReq * http.Request , proxyClient * http.Client , resolver BaseURLResolver , reverseProxy * httputil. ReverseProxy , verbose bool ) {
138147 ctx := originalReq .Context ()
139148
140149 pathVars := mux .Vars (originalReq )
141150 functionName := pathVars ["name" ]
142151 if functionName == "" {
143152 w .Header ().Add (openFaaSInternalHeader , "proxy" )
144153
145- httputil .Errorf (w , http .StatusBadRequest , "Provide function name in the request path" )
154+ fhttputil .Errorf (w , http .StatusBadRequest , "Provide function name in the request path" )
146155 return
147156 }
148157
@@ -152,7 +161,7 @@ func proxyRequest(w http.ResponseWriter, originalReq *http.Request, proxyClient
152161
153162 // TODO: Should record the 404/not found error in Prometheus.
154163 log .Printf ("resolver error: no endpoints for %s: %s\n " , functionName , err .Error ())
155- httputil .Errorf (w , http .StatusServiceUnavailable , "No endpoints available for: %s." , functionName )
164+ fhttputil .Errorf (w , http .StatusServiceUnavailable , "No endpoints available for: %s." , functionName )
156165 return
157166 }
158167
@@ -161,35 +170,42 @@ func proxyRequest(w http.ResponseWriter, originalReq *http.Request, proxyClient
161170
162171 w .Header ().Add (openFaaSInternalHeader , "proxy" )
163172
164- httputil .Errorf (w , http .StatusInternalServerError , "Failed to resolve service: %s." , functionName )
173+ fhttputil .Errorf (w , http .StatusInternalServerError , "Failed to resolve service: %s." , functionName )
165174 return
166175 }
167176
168177 if proxyReq .Body != nil {
169178 defer proxyReq .Body .Close ()
170179 }
171180
172- start := time .Now ()
181+ if verbose {
182+ start := time .Now ()
183+ defer func () {
184+ seconds := time .Since (start )
185+ log .Printf ("%s took %f seconds\n " , functionName , seconds .Seconds ())
186+ }()
187+ }
188+
189+ if v := originalReq .Header .Get ("Accept" ); v == "text/event-stream" {
190+ reverseProxy .ServeHTTP (w , proxyReq )
191+ return
192+ }
193+
173194 response , err := proxyClient .Do (proxyReq .WithContext (ctx ))
174- seconds := time .Since (start )
175195
176196 if err != nil {
177197 log .Printf ("error with proxy request to: %s, %s\n " , proxyReq .URL .String (), err .Error ())
178198
179199 w .Header ().Add (openFaaSInternalHeader , "proxy" )
180200
181- httputil .Errorf (w , http .StatusInternalServerError , "Can't reach service for: %s." , functionName )
201+ fhttputil .Errorf (w , http .StatusInternalServerError , "Can't reach service for: %s." , functionName )
182202 return
183203 }
184204
185205 if response .Body != nil {
186206 defer response .Body .Close ()
187207 }
188208
189- if verbose {
190- log .Printf ("%s took %f seconds\n " , functionName , seconds .Seconds ())
191- }
192-
193209 clientHeader := w .Header ()
194210 copyHeaders (clientHeader , & response .Header )
195211 w .Header ().Set ("Content-Type" , getContentType (originalReq .Header , response .Header ))
0 commit comments