func()

in lambda/rapi/handler/invocationresponse.go [27:123]


func (h *invocationResponseHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
	appCtx := appctx.FromRequest(request)

	server := appctx.LoadResponseSender(appCtx)
	if server == nil {
		log.Panic("Invalid state, cannot access interop server")
	}

	runtime := h.registrationService.GetRuntime()
	if err := runtime.InvocationResponse(); err != nil {
		log.Warn(err)
		rendering.RenderForbiddenWithTypeMsg(writer, request, rendering.ErrorTypeInvalidStateTransition, StateTransitionFailedForRuntimeMessageFormat,
			runtime.GetState().Name(), core.RuntimeInvocationResponseStateName, err)
		return
	}

	invokeID := chi.URLParam(request, "awsrequestid")

	headers := map[string]string{contentTypeHeader: request.Header.Get(contentTypeHeader)}
	if functionResponseMode := request.Header.Get(functionResponseModeHeader); functionResponseMode != "" {
		switch functionResponseMode {
		case StreamingFunctionResponseMode:
			headers[functionResponseModeHeader] = functionResponseMode
		default:
			errHeaders := interop.InvokeResponseHeaders{
				ContentType: request.Header.Get(contentTypeHeader),
			}
			fnError := interop.FunctionError{Type: fatalerror.RuntimeInvalidResponseModeHeader}
			response := &interop.ErrorInvokeResponse{
				Headers:       errHeaders,
				FunctionError: fnError,
				Payload:       []byte{},
			}

			_ = server.SendErrorResponse(chi.URLParam(request, "awsrequestid"), response)
			rendering.RenderInvalidFunctionResponseMode(writer, request)
			return
		}
	}

	response := &interop.StreamableInvokeResponse{
		Headers:  headers,
		Payload:  request.Body,
		Trailers: request.Trailer,
		Request:  &interop.CancellableRequest{Request: request},
	}

	if err := server.SendResponse(invokeID, response); err != nil {
		switch err := err.(type) {
		case *interop.ErrorResponseTooLarge:
			if server.SendErrorResponse(invokeID, err.AsErrorResponse()) != nil {
				rendering.RenderInteropError(writer, request, err)
				return
			}

			appctx.StoreInvokeErrorTraceData(appCtx, &interop.InvokeErrorTraceData{})

			if err := runtime.ResponseSent(); err != nil {
				log.Panic(err)
			}

			rendering.RenderRequestEntityTooLarge(writer, request)
			return

		case *interop.ErrorResponseTooLargeDI:
			// in DirectInvoke case, the (truncated) response is already sent back to the caller
			if err := runtime.ResponseSent(); err != nil {
				log.Panic(err)
			}

			rendering.RenderRequestEntityTooLarge(writer, request)
			return

		case *interop.ErrTruncatedResponse:
			if err := runtime.ResponseSent(); err != nil {
				log.Panic(err)
			}

			rendering.RenderTruncatedHTTPRequestError(writer, request)
			return

		case *interop.ErrInternalPlatformError:
			rendering.RenderInternalServerError(writer, request)
			return

		default:
			rendering.RenderInteropError(writer, request, err)
			return
		}
	}

	if err := runtime.ResponseSent(); err != nil {
		log.Panic(err)
	}

	rendering.RenderAccepted(writer, request)
}