@@ -11,6 +11,7 @@ import (
11
11
"net/http"
12
12
"strconv"
13
13
"strings"
14
+ "sync/atomic"
14
15
"unicode/utf8"
15
16
)
16
17
@@ -111,7 +112,11 @@ func handleFunctionURL(ctx context.Context, event events.LambdaFunctionURLReques
111
112
return def , err
112
113
}
113
114
114
- b := w .body .Bytes ()
115
+ b , err := io .ReadAll (& w .body )
116
+ if err != nil {
117
+ var def events.LambdaFunctionURLResponse
118
+ return def , err
119
+ }
115
120
116
121
if ! w .contentTypeSet {
117
122
w .res .Headers ["Content-Type" ] = http .DetectContentType (b )
@@ -139,10 +144,10 @@ func NewFunctionURLHandler(adapter AdapterFunc) func(context.Context, events.Lam
139
144
140
145
// region streaming
141
146
type functionURLStreamingResponseWriter struct {
142
- headers http.Header
143
- body io. WriteCloser
144
- res * events. LambdaFunctionURLStreamingResponse
145
- resCh chan <- * events.LambdaFunctionURLStreamingResponse
147
+ headers http.Header
148
+ headersWritten int32
149
+ body io. WriteCloser
150
+ resCh chan <- events.LambdaFunctionURLStreamingResponse
146
151
}
147
152
148
153
func (w * functionURLStreamingResponseWriter ) Header () http.Header {
@@ -155,31 +160,33 @@ func (w *functionURLStreamingResponseWriter) Write(p []byte) (int, error) {
155
160
}
156
161
157
162
func (w * functionURLStreamingResponseWriter ) WriteHeader (statusCode int ) {
158
- if w . res == nil {
163
+ if atomic . CompareAndSwapInt32 ( & w . headersWritten , 0 , 1 ) {
159
164
pr , pw := io .Pipe ()
160
165
w .body = pw
161
- w .res = & events.LambdaFunctionURLStreamingResponse {
162
- StatusCode : statusCode ,
163
- Headers : make (map [string ]string ),
164
- Body : pr ,
165
- Cookies : make ([]string , 0 ),
166
- }
166
+
167
+ headers := make (map [string ]string )
168
+ cookies := make ([]string , 0 )
167
169
168
170
for k , values := range w .headers {
169
171
if strings .EqualFold ("set-cookie" , k ) {
170
- w . res . Cookies = values
172
+ cookies = values
171
173
} else {
172
174
if len (values ) == 0 {
173
- w . res . Headers [k ] = ""
175
+ headers [k ] = ""
174
176
} else if len (values ) == 1 {
175
- w . res . Headers [k ] = values [0 ]
177
+ headers [k ] = values [0 ]
176
178
} else {
177
- w . res . Headers [k ] = strings .Join (values , "," )
179
+ headers [k ] = strings .Join (values , "," )
178
180
}
179
181
}
180
182
}
181
183
182
- w .resCh <- w .res
184
+ w .resCh <- events.LambdaFunctionURLStreamingResponse {
185
+ StatusCode : statusCode ,
186
+ Headers : headers ,
187
+ Body : pr ,
188
+ Cookies : cookies ,
189
+ }
183
190
}
184
191
}
185
192
@@ -197,15 +204,15 @@ func handleFunctionURLStreaming(ctx context.Context, event events.LambdaFunction
197
204
return nil , err
198
205
}
199
206
200
- resCh := make (chan * events.LambdaFunctionURLStreamingResponse )
207
+ resCh := make (chan events.LambdaFunctionURLStreamingResponse )
201
208
errCh := make (chan error )
202
209
panicCh := make (chan any )
203
210
204
211
go processRequestFunctionURLStreaming (ctx , req , adapter , resCh , errCh , panicCh )
205
212
206
213
select {
207
214
case res := <- resCh :
208
- return res , nil
215
+ return & res , nil
209
216
case err = <- errCh :
210
217
return nil , err
211
218
case panicV := <- panicCh :
@@ -215,7 +222,7 @@ func handleFunctionURLStreaming(ctx context.Context, event events.LambdaFunction
215
222
}
216
223
}
217
224
218
- func processRequestFunctionURLStreaming (ctx context.Context , req * http.Request , adapter AdapterFunc , resCh chan <- * events.LambdaFunctionURLStreamingResponse , errCh chan <- error , panicCh chan <- any ) {
225
+ func processRequestFunctionURLStreaming (ctx context.Context , req * http.Request , adapter AdapterFunc , resCh chan <- events.LambdaFunctionURLStreamingResponse , errCh chan <- error , panicCh chan <- any ) {
219
226
ctx , cancel := context .WithCancel (ctx )
220
227
defer func () {
221
228
if panicV := recover (); panicV != nil {
@@ -229,8 +236,9 @@ func processRequestFunctionURLStreaming(ctx context.Context, req *http.Request,
229
236
}()
230
237
231
238
w := functionURLStreamingResponseWriter {
232
- headers : make (http.Header ),
233
- resCh : resCh ,
239
+ headers : make (http.Header ),
240
+ headersWritten : 0 ,
241
+ resCh : resCh ,
234
242
}
235
243
236
244
defer w .Close ()
0 commit comments