11package executor
22
33import (
4+ "context"
45 "io"
56 "io/ioutil"
67 "log"
@@ -15,15 +16,18 @@ import (
1516
1617// HTTPFunctionRunner creates and maintains one process responsible for handling all calls
1718type HTTPFunctionRunner struct {
18- Process string
19- ProcessArgs []string
20- Command * exec.Cmd
21- StdinPipe io.WriteCloser
22- StdoutPipe io.ReadCloser
23- Stderr io.Writer
24- Mutex sync.Mutex
25- Client * http.Client
26- UpstreamURL * url.URL
19+ ExecTimeout time.Duration // ExecTimeout the maxmium duration or an upstream function call
20+ ReadTimeout time.Duration
21+ WriteTimeout time.Duration
22+ Process string
23+ ProcessArgs []string
24+ Command * exec.Cmd
25+ StdinPipe io.WriteCloser
26+ StdoutPipe io.ReadCloser
27+ Stderr io.Writer
28+ Mutex sync.Mutex
29+ Client * http.Client
30+ UpstreamURL * url.URL
2731}
2832
2933// Start forks the process used for processing incoming requests
@@ -77,8 +81,7 @@ func (f *HTTPFunctionRunner) Start() error {
7781 }
7882 }()
7983
80- dialTimeout := 3 * time .Second
81- f .Client = makeProxyClient (dialTimeout )
84+ f .Client = makeProxyClient (f .ExecTimeout )
8285
8386 urlValue , upstreamURLErr := url .Parse (os .Getenv ("upstream_url" ))
8487 if upstreamURLErr != nil {
@@ -97,11 +100,37 @@ func (f *HTTPFunctionRunner) Run(req FunctionRequest, contentLength int64, r *ht
97100 for h := range r .Header {
98101 request .Header .Set (h , r .Header .Get (h ))
99102 }
103+ ctx , cancel := context .WithTimeout (context .Background (), f .ExecTimeout )
104+ defer cancel ()
100105
101- res , err := f .Client .Do (request )
106+ res , err := f .Client .Do (request . WithContext ( ctx ) )
102107
103108 if err != nil {
104- log .Println (err )
109+ log .Printf ("Upstream HTTP request error: %s\n " , err .Error ())
110+
111+ // Error unrelated to context / deadline
112+ if ctx .Err () == nil {
113+ w .WriteHeader (http .StatusInternalServerError )
114+
115+ return nil
116+ }
117+
118+ select {
119+ case <- ctx .Done ():
120+ {
121+ if ctx .Err () != nil {
122+ // Error due to timeout / deadline
123+ log .Printf ("Upstream HTTP killed due to exec_timeout: %s\n " , f .ExecTimeout )
124+
125+ w .WriteHeader (http .StatusGatewayTimeout )
126+ return nil
127+ }
128+
129+ }
130+ }
131+
132+ w .WriteHeader (http .StatusInternalServerError )
133+ return err
105134 }
106135
107136 for h := range res .Header {
0 commit comments