diff --git a/include/aws/lambda-runtime/runtime.h b/include/aws/lambda-runtime/runtime.h index be77d93..9597272 100644 --- a/include/aws/lambda-runtime/runtime.h +++ b/include/aws/lambda-runtime/runtime.h @@ -67,28 +67,58 @@ struct invocation_request { inline std::chrono::milliseconds get_time_remaining() const; }; -class invocation_response { -private: +class runtime_response { +protected: /** - * The output of the function which is sent to the lambda caller. + * The response payload from the runtime. */ std::string m_payload; /** * The MIME type of the payload. - * This is always set to 'application/json' in unsuccessful invocations. */ std::string m_content_type; /** - * Flag to distinguish if the contents are for successful or unsuccessful invocations. + * The serialized XRay response header. */ - bool m_success; + std::string m_xray_response; /** - * The serialized XRay response header. + * Instantiate an empty response. */ - std::string m_xray_response; + runtime_response() = default; +public: + /* Create a runtime response with the given payload, content type and xray response. This can be used for constructing an + * initialization error response. For invocation success and failure response, see invocation_response. + */ + runtime_response(std::string const& payload, std::string const& content_type, std::string const& xray_response) + : m_payload(payload), m_content_type(content_type), m_xray_response(xray_response) + { + } + + /** + * Get the payload string. The string is assumed to be UTF-8 encoded. + */ + std::string const& get_payload() const { return m_payload; } + + /** + * Get the MIME type of the payload. + */ + std::string const& get_content_type() const { return m_content_type; } + + /** + * Get the XRay response string. The string is assumed to be UTF-8 encoded. + */ + std::string const& get_xray_response() const { return m_xray_response; } +}; + +class invocation_response: public runtime_response { +private: + /** + * Flag to distinguish if the contents are for successful or unsuccessful invocations. + */ + bool m_success; /** * Instantiate an empty response. Used by the static functions 'success' and 'failure' to create a populated @@ -102,12 +132,10 @@ public: // To support clients that need to control the entire error response body (e.g. adding a stack trace), this // constructor should be used instead. // Note: adding an overload to invocation_response::failure is not feasible since the parameter types are the same. - invocation_response(std::string const& payload, std::string const& content_type, bool success, std::string const& xray_response): - m_payload(payload), - m_content_type(content_type), - m_success(success), - m_xray_response(xray_response) - {} + invocation_response(std::string const& payload, std::string const& content_type, bool success, std::string const& xray_response) + : runtime_response(payload, content_type, xray_response), m_success(success) + { + } /** * Create a successful invocation response with the given payload and content-type. @@ -120,25 +148,10 @@ public: */ static invocation_response failure(std::string const& error_message, std::string const& error_type, std::string const& xray_response); - /** - * Get the MIME type of the payload. - */ - std::string const& get_content_type() const { return m_content_type; } - - /** - * Get the payload string. The string is assumed to be UTF-8 encoded. - */ - std::string const& get_payload() const { return m_payload; } - /** * Returns true if the payload and content-type are set. Returns false if the error message and error types are set. */ bool is_success() const { return m_success; } - - /** - * Get the XRay response string. The string isassumed to be UTF-8 encoded. - */ - std::string const& get_xray_response() const { return m_xray_response; } }; struct no_result { @@ -167,13 +180,19 @@ public: */ post_outcome post_failure(std::string const& request_id, invocation_response const& handler_response); + /** + * Tells lambda that the runtime has failed during initialization. + */ + post_outcome post_init_error(runtime_response const& init_error_response); + private: void set_curl_next_options(); void set_curl_post_result_options(); post_outcome do_post( std::string const& url, - std::string const& request_id, - invocation_response const& handler_response); + std::string const& content_type, + std::string const& payload, + std::string const& xray_response); private: std::array const m_endpoints; diff --git a/src/runtime.cpp b/src/runtime.cpp index d895c4b..659666e 100644 --- a/src/runtime.cpp +++ b/src/runtime.cpp @@ -311,37 +311,44 @@ runtime::next_outcome runtime::get_next() runtime::post_outcome runtime::post_success(std::string const& request_id, invocation_response const& handler_response) { std::string const url = m_endpoints[Endpoints::RESULT] + request_id + "/response"; - return do_post(url, request_id, handler_response); + return do_post(url, handler_response.get_content_type(), handler_response.get_payload(), handler_response.get_xray_response()); } runtime::post_outcome runtime::post_failure(std::string const& request_id, invocation_response const& handler_response) { std::string const url = m_endpoints[Endpoints::RESULT] + request_id + "/error"; - return do_post(url, request_id, handler_response); + return do_post(url, handler_response.get_content_type(), handler_response.get_payload(), handler_response.get_xray_response()); +} + +runtime::post_outcome runtime::post_init_error(runtime_response const& init_error_response) +{ + std::string const url = m_endpoints[Endpoints::INIT]; + return do_post(url, init_error_response.get_content_type(), init_error_response.get_payload(), init_error_response.get_xray_response()); } runtime::post_outcome runtime::do_post( std::string const& url, - std::string const& request_id, - invocation_response const& handler_response) + std::string const& content_type, + std::string const& payload, + std::string const& xray_response) { set_curl_post_result_options(); curl_easy_setopt(m_curl_handle, CURLOPT_URL, url.c_str()); logging::log_info(LOG_TAG, "Making request to %s", url.c_str()); curl_slist* headers = nullptr; - if (handler_response.get_content_type().empty()) { + if (content_type.empty()) { headers = curl_slist_append(headers, "content-type: text/html"); } else { - headers = curl_slist_append(headers, ("content-type: " + handler_response.get_content_type()).c_str()); + headers = curl_slist_append(headers, ("content-type: " + content_type).c_str()); } - headers = curl_slist_append(headers, ("lambda-runtime-function-xray-error-cause: " + handler_response.get_xray_response()).c_str()); + headers = curl_slist_append(headers, ("lambda-runtime-function-xray-error-cause: " + xray_response).c_str()); headers = curl_slist_append(headers, "Expect:"); headers = curl_slist_append(headers, "transfer-encoding:"); headers = curl_slist_append(headers, get_user_agent_header().c_str()); - auto const& payload = handler_response.get_payload(); + logging::log_debug( LOG_TAG, "calculating content length... %s", ("content-length: " + std::to_string(payload.length())).c_str()); headers = curl_slist_append(headers, ("content-length: " + std::to_string(payload.length())).c_str()); @@ -358,10 +365,10 @@ runtime::post_outcome runtime::do_post( if (curl_code != CURLE_OK) { logging::log_debug( LOG_TAG, - "CURL returned error code %d - %s, for invocation %s", + "CURL returned error code %d - %s, when calling %s", curl_code, curl_easy_strerror(curl_code), - request_id.c_str()); + url.c_str()); return aws::http::response_code::REQUEST_NOT_MADE; }