@@ -83,43 +83,16 @@ func (s *Server) Manager() *ContainerManager {
8383 return s .manager
8484}
8585
86- func (s * Server ) RunLambdaErr (w http.ResponseWriter , r * http.Request ) * httpErr {
87- urlParts := getUrlComponents (r )
88- if len (urlParts ) < 2 {
89- return newHttpErr (
90- "Name of image to run required" ,
91- http .StatusBadRequest )
92- }
93-
94- // components represent runLambda[0]/<name_of_container>[1]/<extra_things>...
95- // ergo we want [1] for name of container
96- img := urlParts [1 ]
97- i := strings .Index (img , "?" )
98- if i >= 0 {
99- img = img [:i - 1 ]
100- }
101-
86+ func (s * Server ) ForwardToContainer (lambda_name string , r * http.Request , input []byte ) ([]byte , * http.Response , * httpErr ) {
10287 // we'll ask docker manager to ensure the img is ready to accept requests
10388 // This will either start the img, or unpause a started one
104- port , err := s .manager .DockerMakeReady (img )
89+ port , err := s .manager .DockerMakeReady (lambda_name )
10590 if err != nil {
106- return newHttpErr (
91+ return nil , nil , newHttpErr (
10792 err .Error (),
10893 http .StatusInternalServerError )
10994 }
11095
111- // read incoming request
112- rbody := []byte {}
113- if r .Body != nil {
114- defer r .Body .Close ()
115- rbody , err = ioutil .ReadAll (r .Body )
116- if err != nil {
117- return newHttpErr (
118- err .Error (),
119- http .StatusInternalServerError )
120- }
121- }
122-
12396 // forward request to container. r and w are the server
12497 // request and response respectively. r2 and w2 are the
12598 // container request and response respectively.
@@ -129,15 +102,11 @@ func (s *Server) RunLambdaErr(w http.ResponseWriter, r *http.Request) *httpErr {
129102
130103 // TODO(tyler): some sort of smarter backoff. Or, a better
131104 // way to detect a started container.
132- for i := 0 ; i < 10 ; i ++ {
133- if i > 0 {
134- log .Printf ("retry request\n " )
135- time .Sleep (time .Duration (i * 10 ) * time .Millisecond )
136- }
137-
138- r2 , err := http .NewRequest ("POST" , url , bytes .NewReader (rbody ))
105+ max_tries := 10
106+ for tries := 1 ; ; tries ++ {
107+ r2 , err := http .NewRequest ("POST" , url , bytes .NewReader (input ))
139108 if err != nil {
140- return newHttpErr (
109+ return nil , nil , newHttpErr (
141110 err .Error (),
142111 http .StatusInternalServerError )
143112 }
@@ -147,34 +116,75 @@ func (s *Server) RunLambdaErr(w http.ResponseWriter, r *http.Request) *httpErr {
147116 w2 , err := client .Do (r2 )
148117 if err != nil {
149118 log .Printf ("request to container failed with %v\n " , err )
119+ if tries == max_tries {
120+ return nil , nil , newHttpErr (
121+ err .Error (),
122+ http .StatusInternalServerError )
123+ }
124+ log .Printf ("retry request\n " )
125+ time .Sleep (time .Duration (tries * 10 ) * time .Millisecond )
150126 continue
151127 }
152128
153129 defer w2 .Body .Close ()
154130 wbody , err := ioutil .ReadAll (w2 .Body )
155131 if err != nil {
156- return newHttpErr (
132+ return nil , nil , newHttpErr (
157133 err .Error (),
158134 http .StatusInternalServerError )
159135 }
136+ return wbody , w2 , nil
137+ }
138+ }
160139
161- // forward response
162- // TODO(tyler): origins should be configurable
163- w .Header ().Set ("Access-Control-Allow-Origin" , "*" )
164- w .Header ().Set ("Access-Control-Allow-Methods" ,
165- "GET, PUT, POST, DELETE, OPTIONS" )
166- w .Header ().Set ("Access-Control-Allow-Headers" ,
167- "Content-Type, Content-Range, Content-Disposition, Content-Description" )
168-
169- w .WriteHeader (w2 .StatusCode )
140+ func (s * Server ) RunLambdaErr (w http.ResponseWriter , r * http.Request ) * httpErr {
141+ // components represent runLambda[0]/<name_of_container>[1]/<extra_things>...
142+ // ergo we want [1] for name of container
143+ urlParts := getUrlComponents (r )
144+ if len (urlParts ) < 2 {
145+ return newHttpErr (
146+ "Name of image to run required" ,
147+ http .StatusBadRequest )
148+ }
149+ img := urlParts [1 ]
150+ i := strings .Index (img , "?" )
151+ if i >= 0 {
152+ img = img [:i - 1 ]
153+ }
170154
171- if _ , err := w .Write (wbody ); err != nil {
155+ // read request
156+ rbody := []byte {}
157+ if r .Body != nil {
158+ defer r .Body .Close ()
159+ var err error
160+ rbody , err = ioutil .ReadAll (r .Body )
161+ if err != nil {
172162 return newHttpErr (
173163 err .Error (),
174164 http .StatusInternalServerError )
175165 }
166+ }
176167
177- return nil
168+ // forward to container
169+ wbody , w2 , err := s .ForwardToContainer (img , r , rbody )
170+ if err != nil {
171+ return err
172+ }
173+
174+ // write response
175+ // TODO(tyler): origins should be configurable
176+ w .Header ().Set ("Access-Control-Allow-Origin" , "*" )
177+ w .Header ().Set ("Access-Control-Allow-Methods" ,
178+ "GET, PUT, POST, DELETE, OPTIONS" )
179+ w .Header ().Set ("Access-Control-Allow-Headers" ,
180+ "Content-Type, Content-Range, Content-Disposition, Content-Description" )
181+
182+ w .WriteHeader (w2 .StatusCode )
183+
184+ if _ , err := w .Write (wbody ); err != nil {
185+ return newHttpErr (
186+ err .Error (),
187+ http .StatusInternalServerError )
178188 }
179189
180190 return nil
0 commit comments