in lambda/core/directinvoke/directinvoke.go [398:453]
func sendPayloadLimitedResponse(payload io.Reader, trailers http.Header, w http.ResponseWriter, sendResponseChan chan *interop.InvokeResponseMetrics, runtimeCalledResponse bool) (err error) {
functionResponseMode, err := parseFunctionResponseMode(w)
if err != nil {
return err
}
// non-streaming invoke request but runtime is streaming: predefine Trailer headers
if functionResponseMode == interop.FunctionResponseModeStreaming {
w.Header().Add("Trailer", FunctionErrorTypeTrailer)
w.Header().Add("Trailer", FunctionErrorBodyTrailer)
}
startReadingResponseMonoTimeMs := metering.Monotime()
// Setting the limit to MaxDirectResponseSize + 1 so we can do
// readBytes > MaxDirectResponseSize to check if the response is oversized.
// As the response is allowed to be of the size MaxDirectResponseSize but not larger than it.
written, err := io.Copy(w, io.LimitReader(payload, MaxDirectResponseSize+1))
// non-streaming invoke request but runtime is streaming: set response trailers
if functionResponseMode == interop.FunctionResponseModeStreaming {
w.Header().Set(FunctionErrorTypeTrailer, trailers.Get(FunctionErrorTypeTrailer))
w.Header().Set(FunctionErrorBodyTrailer, trailers.Get(FunctionErrorBodyTrailer))
}
isNotStreamingInvoke := InvokeResponseMode != interop.InvokeResponseModeStreaming
if err != nil {
w.Header().Set(EndOfResponseTrailer, EndOfResponseTruncated)
err = &interop.ErrTruncatedResponse{}
} else if isNotStreamingInvoke && written == MaxDirectResponseSize+1 {
w.Header().Set(EndOfResponseTrailer, EndOfResponseOversized)
err = &interop.ErrorResponseTooLargeDI{
ErrorResponseTooLarge: interop.ErrorResponseTooLarge{
ResponseSize: int(written),
MaxResponseSize: int(MaxDirectResponseSize),
},
}
} else {
w.Header().Set(EndOfResponseTrailer, EndOfResponseComplete)
}
sendResponseChan <- &interop.InvokeResponseMetrics{
ProducedBytes: int64(written),
StartReadingResponseMonoTimeMs: startReadingResponseMonoTimeMs,
FinishReadingResponseMonoTimeMs: metering.Monotime(),
TimeShapedNs: int64(-1),
OutboundThroughputBps: int64(-1),
// FIXME:
// We should use InvokeResponseMode here, because only when it's streaming we're interested
// on it. If the invoke is buffered, we don't generate streaming metrics, even if the
// function response mode is streaming.
FunctionResponseMode: interop.FunctionResponseModeBuffered,
RuntimeCalledResponse: runtimeCalledResponse,
}
return
}