Skip to content

Commit ba5b0a4

Browse files
authored
transcoding: Handle RequestStatus error (istio#305)
* Handle RequestStatus error * Add test for RequestStatus error
1 parent 36ac1b1 commit ba5b0a4

File tree

3 files changed

+67
-2
lines changed

3 files changed

+67
-2
lines changed

src/envoy/transcoding/filter.cc

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
*/
1515
#include "src/envoy/transcoding/filter.h"
1616

17+
#include "common/http/utility.h"
1718
#include "google/protobuf/descriptor.h"
1819
#include "google/protobuf/descriptor.pb.h"
1920
#include "google/protobuf/message.h"
@@ -59,6 +60,17 @@ Http::FilterHeadersStatus Instance::decodeHeaders(Http::HeaderMap& headers,
5960

6061
request_in_.Finish();
6162

63+
const auto& request_status = transcoder_->RequestStatus();
64+
if (!request_status.ok()) {
65+
log().debug("Transcoding request error " + request_status.ToString());
66+
error_ = true;
67+
Http::Utility::sendLocalReply(
68+
*decoder_callbacks_, Http::Code::BadRequest,
69+
request_status.error_message().ToString());
70+
71+
return Http::FilterHeadersStatus::StopIteration;
72+
}
73+
6274
Buffer::OwnedImpl data;
6375
ReadToBuffer(transcoder_->RequestOutput(), data);
6476

@@ -67,7 +79,7 @@ Http::FilterHeadersStatus Instance::decodeHeaders(Http::HeaderMap& headers,
6779
}
6880
}
6981
} else {
70-
log().debug("No transcoding" + status.ToString());
82+
log().debug("No transcoding: " + status.ToString());
7183
}
7284

7385
return Http::FilterHeadersStatus::Continue;
@@ -76,12 +88,30 @@ Http::FilterHeadersStatus Instance::decodeHeaders(Http::HeaderMap& headers,
7688
Http::FilterDataStatus Instance::decodeData(Buffer::Instance& data,
7789
bool end_stream) {
7890
log().debug("Transcoding::Instance::decodeData");
91+
92+
if (error_) {
93+
return Http::FilterDataStatus::StopIterationNoBuffer;
94+
}
95+
7996
if (transcoder_) {
8097
request_in_.Move(data);
8198

99+
if (end_stream) {
100+
request_in_.Finish();
101+
}
102+
82103
ReadToBuffer(transcoder_->RequestOutput(), data);
83104

84-
// TODO: Check RequesStatus
105+
const auto& request_status = transcoder_->RequestStatus();
106+
107+
if (!request_status.ok()) {
108+
log().debug("Transcoding request error " + request_status.ToString());
109+
error_ = true;
110+
Http::Utility::sendLocalReply(*decoder_callbacks_, Http::Code::BadRequest,
111+
request_status.error_message().ToString());
112+
113+
return Http::FilterDataStatus::StopIterationNoBuffer;
114+
}
85115
}
86116

87117
return Http::FilterDataStatus::Continue;
@@ -111,6 +141,10 @@ void Instance::setDecoderFilterCallbacks(
111141
Http::FilterHeadersStatus Instance::encodeHeaders(Http::HeaderMap& headers,
112142
bool end_stream) {
113143
log().debug("Transcoding::Instance::encodeHeaders");
144+
if (error_) {
145+
return Http::FilterHeadersStatus::Continue;
146+
}
147+
114148
if (transcoder_) {
115149
headers.insertContentType().value(kJsonContentType);
116150
}
@@ -120,6 +154,10 @@ Http::FilterHeadersStatus Instance::encodeHeaders(Http::HeaderMap& headers,
120154
Http::FilterDataStatus Instance::encodeData(Buffer::Instance& data,
121155
bool end_stream) {
122156
log().debug("Transcoding::Instance::encodeData");
157+
if (error_) {
158+
return Http::FilterDataStatus::Continue;
159+
}
160+
123161
if (transcoder_) {
124162
response_in_.Move(data);
125163

src/envoy/transcoding/filter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ class Instance : public Http::StreamFilter,
6464
EnvoyInputStream response_in_;
6565
Http::StreamDecoderFilterCallbacks* decoder_callbacks_{nullptr};
6666
Http::StreamEncoderFilterCallbacks* encoder_callbacks_{nullptr};
67+
68+
bool error_{false};
6769
};
6870

6971
} // namespace Transcoding

src/envoy/transcoding/filter_test.cc

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "gtest/gtest.h"
3232

3333
using testing::_;
34+
using testing::Invoke;
3435
using testing::NiceMock;
3536
using testing::Return;
3637
using testing::ReturnPointee;
@@ -145,6 +146,30 @@ TEST_F(GrpcHttpJsonTranscodingFilterTest, TranscodingUnaryPost) {
145146
filter_.decodeTrailers(response_trailers));
146147
}
147148

149+
TEST_F(GrpcHttpJsonTranscodingFilterTest, TranscodingUnaryError) {
150+
Http::TestHeaderMapImpl request_headers{{"content-type", "application/json"},
151+
{":method", "POST"},
152+
{":path", "/shelf"}};
153+
154+
EXPECT_EQ(Http::FilterHeadersStatus::Continue,
155+
filter_.decodeHeaders(request_headers, false));
156+
EXPECT_EQ("application/grpc", request_headers.get_("content-type"));
157+
EXPECT_EQ("/bookstore.Bookstore/CreateShelf", request_headers.get_(":path"));
158+
EXPECT_EQ("trailers", request_headers.get_("te"));
159+
160+
Buffer::OwnedImpl request_data{"{\"theme\": \"Children\""};
161+
162+
EXPECT_CALL(decoder_callbacks_, encodeHeaders_(_, false))
163+
.WillOnce(Invoke([](Http::HeaderMap& headers, bool end_stream) {
164+
EXPECT_STREQ("400", headers.Status()->value().c_str());
165+
}));
166+
EXPECT_CALL(decoder_callbacks_, encodeData(_, true));
167+
168+
EXPECT_EQ(Http::FilterDataStatus::StopIterationNoBuffer,
169+
filter_.decodeData(request_data, true));
170+
EXPECT_EQ(0, request_data.length());
171+
}
172+
148173
} // namespace Transcoding
149174
} // namespace Grpc
150175
} // namespace Envoy

0 commit comments

Comments
 (0)