Wrap converts an http.Handler into a Lambda request handler. Only Lambda Function URLs configured with `InvokeMode: RESPONSE_STREAM` are supported with the returned handler. The response body of the handler will conform to the content-type `application/vnd.awslambda.http-integration-response`.
(handler http.Handler)
| 103 | // Only Lambda Function URLs configured with `InvokeMode: RESPONSE_STREAM` are supported with the returned handler. |
| 104 | // The response body of the handler will conform to the content-type `application/vnd.awslambda.http-integration-response`. |
| 105 | func Wrap(handler http.Handler) func(context.Context, *events.LambdaFunctionURLRequest) (*events.LambdaFunctionURLStreamingResponse, error) { |
| 106 | return func(ctx context.Context, request *events.LambdaFunctionURLRequest) (*events.LambdaFunctionURLStreamingResponse, error) { |
| 107 | |
| 108 | var body io.Reader = strings.NewReader(request.Body) |
| 109 | if request.IsBase64Encoded { |
| 110 | body = base64.NewDecoder(base64.StdEncoding, body) |
| 111 | } |
| 112 | url := "https://" + request.RequestContext.DomainName + request.RawPath |
| 113 | if request.RawQueryString != "" { |
| 114 | url += "?" + request.RawQueryString |
| 115 | } |
| 116 | ctx = context.WithValue(ctx, requestContextKey{}, request) |
| 117 | httpRequest, err := http.NewRequestWithContext(ctx, request.RequestContext.HTTP.Method, url, body) |
| 118 | if err != nil { |
| 119 | return nil, err |
| 120 | } |
| 121 | httpRequest.RemoteAddr = request.RequestContext.HTTP.SourceIP |
| 122 | for k, v := range request.Headers { |
| 123 | httpRequest.Header.Add(k, v) |
| 124 | } |
| 125 | |
| 126 | ready := make(chan header) // Signals when it's OK to start returning the response body to Lambda |
| 127 | r, w := io.Pipe() |
| 128 | responseWriter := &httpResponseWriter{writer: w, ready: ready} |
| 129 | if detectContentType, ok := ctx.Value(detectContentTypeContextKey{}).(bool); ok { |
| 130 | responseWriter.detectContentType = detectContentType |
| 131 | } |
| 132 | go func() { |
| 133 | defer close(ready) |
| 134 | defer w.Close() // TODO: recover and CloseWithError the any panic value once the runtime API client supports plumbing fatal errors through the reader |
| 135 | //nolint:errcheck |
| 136 | defer responseWriter.Write(nil) // force default status, headers, content type detection, if none occurred during the execution of the handler |
| 137 | handler.ServeHTTP(responseWriter, httpRequest) |
| 138 | }() |
| 139 | header := <-ready |
| 140 | response := &events.LambdaFunctionURLStreamingResponse{ |
| 141 | Body: r, |
| 142 | StatusCode: header.code, |
| 143 | } |
| 144 | if len(header.header) > 0 { |
| 145 | response.Headers = make(map[string]string, len(header.header)) |
| 146 | for k, v := range header.header { |
| 147 | if k == "Set-Cookie" { |
| 148 | response.Cookies = v |
| 149 | } else { |
| 150 | response.Headers[k] = strings.Join(v, ",") |
| 151 | } |
| 152 | } |
| 153 | } |
| 154 | return response, nil |
| 155 | } |
| 156 | } |
| 157 | |
| 158 | // Start wraps a http.Handler and calls lambda.StartHandlerFunc |
| 159 | // Only supports: |
searching dependent graphs…