diff --git a/src/brpc/controller.h b/src/brpc/controller.h index 41f1267de7..658cc6957c 100644 --- a/src/brpc/controller.h +++ b/src/brpc/controller.h @@ -143,6 +143,7 @@ friend void policy::ProcessThriftRequest(InputMessageBase*); static const uint32_t FLAGS_ALWAYS_PRINT_PRIMITIVE_FIELDS = (1 << 18); static const uint32_t FLAGS_HEALTH_CHECK_CALL = (1 << 19); static const uint32_t FLAGS_PB_SINGLE_REPEATED_TO_ARRAY = (1 << 20); + static const uint32_t FLAGS_MANAGE_HTTP_BODY_ON_ERROR = (1 << 21); public: struct Inheritable { @@ -398,6 +399,16 @@ friend void policy::ProcessThriftRequest(InputMessageBase*); // directly instead of being serialized into protobuf messages. butil::IOBuf& response_attachment() { return _response_attachment; } + // Response Body of a failed HTTP call is set to be ErrorText() by default, + // even if response_attachment() is non-empty. + // If this flag is true, the http body of a failed HTTP call will not be + // replaced by ErrorText() and should be managed by user self. + void manage_http_body_on_error(bool manage_or_not) + { set_flag(FLAGS_MANAGE_HTTP_BODY_ON_ERROR, manage_or_not); } + + bool does_manage_http_body_on_error() const + { return has_flag(FLAGS_MANAGE_HTTP_BODY_ON_ERROR); } + // Create a ProgressiveAttachment to write (often after RPC). // If `stop_style' is FORCE_STOP, the underlying socket will be failed // immediately when the socket becomes idle or server is stopped. diff --git a/src/brpc/policy/http_rpc_protocol.cpp b/src/brpc/policy/http_rpc_protocol.cpp index 6e32598f3a..6927e377ef 100644 --- a/src/brpc/policy/http_rpc_protocol.cpp +++ b/src/brpc/policy/http_rpc_protocol.cpp @@ -847,7 +847,9 @@ HttpResponseSender::~HttpResponseSender() { bool grpc_compressed = false; if (cntl->Failed()) { - cntl->response_attachment().clear(); + if (!cntl->does_manage_http_body_on_error()) { + cntl->response_attachment().clear(); + } if (!is_grpc) { // Set status-code with default value(converted from error code) // if user did not set it. @@ -858,12 +860,14 @@ HttpResponseSender::~HttpResponseSender() { res_header->SetHeader(common->ERROR_CODE, butil::string_printf("%d", cntl->ErrorCode())); - // Fill body with ErrorText. - // user may compress the output and change content-encoding. However - // body is error-text right now, remove the header. - res_header->RemoveHeader(common->CONTENT_ENCODING); - res_header->set_content_type(common->CONTENT_TYPE_TEXT); - cntl->response_attachment().append(cntl->ErrorText()); + if (!cntl->does_manage_http_body_on_error()) { + // Fill body with ErrorText. + // user may compress the output and change content-encoding. However + // body is error-text right now, remove the header. + res_header->RemoveHeader(common->CONTENT_ENCODING); + res_header->set_content_type(common->CONTENT_TYPE_TEXT); + cntl->response_attachment().append(cntl->ErrorText()); + } } } else if (cntl->has_progressive_writer()) { // Transfer-Encoding is supported since HTTP/1.1