1
1
#pragma once
2
2
#include " json_pipe_req.h"
3
- #include " viewer.h"
4
- #include < library/cpp/json/json_writer.h>
5
3
#include < ydb/core/grpc_services/local_rpc/local_rpc.h>
6
4
7
- namespace NKikimr {
8
- namespace NViewer {
5
+ namespace NKikimr ::NViewer {
9
6
10
7
struct TEvLocalRpcPrivate {
11
8
enum EEv {
@@ -26,41 +23,27 @@ struct TEvLocalRpcPrivate {
26
23
};
27
24
};
28
25
29
- using namespace NActors ;
30
- using NSchemeShard::TEvSchemeShard;
31
-
32
26
template <class TProtoRequest , class TProtoResponse , class TProtoResult , class TProtoService , class TRpcEv >
33
- class TJsonLocalRpc : public TActorBootstrapped <TJsonLocalRpc<TProtoRequest, TProtoResponse, TProtoResult, TProtoService, TRpcEv>> {
27
+ class TJsonLocalRpc : public TViewerPipeClient {
34
28
using TThis = TJsonLocalRpc<TProtoRequest, TProtoResponse, TProtoResult, TProtoService, TRpcEv>;
35
- using TBase = TActorBootstrapped<TThis>;
36
-
37
- using TBase::Send;
38
- using TBase::PassAway;
39
- using TBase::Become;
29
+ using TBase = TViewerPipeClient;
40
30
41
31
protected:
42
- IViewer* Viewer;
43
- NMon::TEvHttpInfo::TPtr Event;
44
- TProtoRequest Request;
32
+ using TBase::ReplyAndPassAway;
33
+ std::vector<HTTP_METHOD> AllowedMethods = {};
45
34
TAutoPtr<TEvLocalRpcPrivate::TEvGrpcRequestResult<TProtoResult>> Result;
46
-
47
- TJsonSettings JsonSettings;
48
- ui32 Timeout = 0 ;
49
- TString Database;
50
35
NThreading::TFuture<TProtoResponse> RpcFuture;
51
36
52
37
public:
53
38
static constexpr NKikimrServices::TActivity::EType ActorActivityType () {
54
39
return NKikimrServices::TActivity::VIEWER_HANDLER;
55
40
}
56
41
57
- TJsonLocalRpc (IViewer* viewer, NMon::TEvHttpInfo::TPtr &ev)
58
- : Viewer(viewer)
59
- , Event(ev)
42
+ TJsonLocalRpc (IViewer* viewer, NMon::TEvHttpInfo::TPtr& ev)
43
+ : TBase(viewer, ev, TProtoRequest::descriptor()->name ())
60
44
{}
61
45
62
- TProtoRequest Params2Proto (const TCgiParameters& params) {
63
- TProtoRequest request;
46
+ void Params2Proto (const TCgiParameters& params, TProtoRequest& request) {
64
47
using google::protobuf::Descriptor;
65
48
using google::protobuf::Reflection;
66
49
using google::protobuf::FieldDescriptor;
@@ -110,44 +93,52 @@ class TJsonLocalRpc : public TActorBootstrapped<TJsonLocalRpc<TProtoRequest, TPr
110
93
}
111
94
}
112
95
}
113
- return request;
114
96
}
115
97
116
- TProtoRequest Params2Proto () {
117
- TProtoRequest request;
118
- NProtobufJson::TJson2ProtoConfig json2ProtoConfig;
119
- auto postData = Event->Get ()->Request .GetPostContent ();
120
- if (!postData.empty ()) {
121
- try {
122
- NProtobufJson::Json2Proto (postData, request, json2ProtoConfig);
123
- }
124
- catch (const yexception& e) {
125
- ReplyAndPassAway (Viewer->GetHTTPBADREQUEST (Event->Get (), " text/plain" , e.what ()));
98
+ bool ValidateProto (TProtoRequest& request) {
99
+ using google::protobuf::Descriptor;
100
+ using google::protobuf::Reflection;
101
+ using google::protobuf::FieldDescriptor;
102
+ const Descriptor& descriptor = *TProtoRequest::GetDescriptor ();
103
+ const Reflection& reflection = *TProtoRequest::GetReflection ();
104
+ for (int idx = 0 ; idx < descriptor.field_count (); ++idx) {
105
+ const FieldDescriptor* field = descriptor.field (idx);
106
+ const auto & options (field->options ());
107
+ if (options.HasExtension (Ydb::required)) {
108
+ if (options.GetExtension (Ydb::required)) {
109
+ if (!reflection.HasField (request, field)) {
110
+ ReplyAndPassAway (GetHTTPBADREQUEST (" text/plain" , TStringBuilder () << " field '" << field->name () << " ' is required" ));
111
+ return false ;
112
+ }
113
+ }
126
114
}
127
- } else {
128
- const auto & params (Event->Get ()->Request .GetParams ());
129
- return Params2Proto (params);
130
115
}
131
- return request ;
116
+ return true ;
132
117
}
133
118
134
- bool PostToRequest ( ) {
119
+ bool Params2Proto (TProtoRequest& request ) {
135
120
auto postData = Event->Get ()->Request .GetPostContent ();
136
121
if (!postData.empty ()) {
137
122
try {
138
- NProtobufJson::Json2Proto (postData, Request, {});
139
- return true ;
123
+ NProtobufJson::Json2Proto (postData, request);
140
124
}
141
125
catch (const yexception& e) {
142
- ReplyAndPassAway (Viewer-> GetHTTPBADREQUEST (Event-> Get (), " text/plain" , e.what ()));
126
+ ReplyAndPassAway (GetHTTPBADREQUEST (" text/plain" , e.what ()));
143
127
return false ;
144
128
}
129
+ } else {
130
+ const auto & params (Event->Get ()->Request .GetParams ());
131
+ Params2Proto (params, request);
132
+ }
133
+ if (!ValidateProto (request)) {
134
+ return false ;
145
135
}
146
136
return true ;
147
137
}
148
138
149
- void SendGrpcRequest () {
150
- RpcFuture = NRpcService::DoLocalRpc<TRpcEv>(std::move (Request), Database, Event->Get ()->UserToken , TlsActivationContext->ActorSystem ());
139
+ void SendGrpcRequest (TProtoRequest&& request) {
140
+ // TODO(xenoxeno): pass trace id
141
+ RpcFuture = NRpcService::DoLocalRpc<TRpcEv>(std::move (request), Database, Event->Get ()->UserToken , TlsActivationContext->ActorSystem ());
151
142
RpcFuture.Subscribe ([actorId = TBase::SelfId (), actorSystem = TlsActivationContext->ActorSystem ()]
152
143
(const NThreading::TFuture<TProtoResponse>& future) {
153
144
auto & response = future.GetValueSync ();
@@ -173,14 +164,21 @@ class TJsonLocalRpc : public TActorBootstrapped<TJsonLocalRpc<TProtoRequest, TPr
173
164
}
174
165
175
166
virtual void Bootstrap () {
176
- const auto & params (Event->Get ()->Request .GetParams ());
177
- JsonSettings.EnumAsNumbers = !FromStringWithDefault<bool >(params.Get (" enums" ), true );
178
- JsonSettings.UI64AsString = !FromStringWithDefault<bool >(params.Get (" ui64" ), true );
179
- Timeout = FromStringWithDefault<ui32>(params.Get (" timeout" ), 10000 );
180
-
181
- SendGrpcRequest ();
182
-
183
- Become (&TThis::StateRequested, TDuration::MilliSeconds (Timeout), new TEvents::TEvWakeup ());
167
+ if (!AllowedMethods.empty () && std::find (AllowedMethods.begin (), AllowedMethods.end (), Event->Get ()->Request .GetMethod ()) == AllowedMethods.end ()) {
168
+ return ReplyAndPassAway (GetHTTPBADREQUEST (" text/plain" , " Method is not allowed" ));
169
+ }
170
+ if (Database.empty ()) {
171
+ return ReplyAndPassAway (GetHTTPBADREQUEST (" text/plain" , " field 'database' is required" ));
172
+ }
173
+ if (TBase::NeedToRedirect ()) {
174
+ return ;
175
+ }
176
+ TProtoRequest request;
177
+ if (!Params2Proto (request)) {
178
+ return ;
179
+ }
180
+ SendGrpcRequest (std::move (request));
181
+ Become (&TThis::StateRequested, Timeout, new TEvents::TEvWakeup ());
184
182
}
185
183
186
184
void Handle (typename TEvLocalRpcPrivate::TEvGrpcRequestResult<TProtoResult>::TPtr& ev) {
@@ -197,38 +195,24 @@ class TJsonLocalRpc : public TActorBootstrapped<TJsonLocalRpc<TProtoRequest, TPr
197
195
198
196
void ReplyAndPassAway () {
199
197
if (Result && Result->Status ) {
200
- if (!Result->Status ->IsSuccess ()) {
198
+ if (Result->Status ->IsSuccess ()) {
199
+ return ReplyAndPassAway (GetHTTPOKJSON (Result->Message ));
200
+ } else {
201
201
NJson::TJsonValue json;
202
202
TString message;
203
203
MakeJsonErrorReply (json, message, Result->Status .value ());
204
204
TStringStream stream;
205
205
NJson::WriteJson (&stream, &json);
206
206
if (Result->Status ->GetStatus () == NYdb::EStatus::UNAUTHORIZED) {
207
- return ReplyAndPassAway (Viewer-> GetHTTPFORBIDDEN (Event-> Get (), " application/json" , stream.Str ()));
207
+ return ReplyAndPassAway (GetHTTPFORBIDDEN (" application/json" , stream.Str ()), message );
208
208
} else {
209
- return ReplyAndPassAway (Viewer-> GetHTTPBADREQUEST (Event-> Get (), " application/json" , stream.Str ()));
209
+ return ReplyAndPassAway (GetHTTPBADREQUEST (" application/json" , stream.Str ()), message );
210
210
}
211
- } else {
212
- TStringStream json;
213
- TProtoToJson::ProtoToJson (json, Result->Message , JsonSettings);
214
- return ReplyAndPassAway (Viewer->GetHTTPOKJSON (Event->Get (), json.Str ()));
215
211
}
216
212
} else {
217
- return ReplyAndPassAway (Viewer-> GetHTTPINTERNALERROR (Event-> Get ()) );
213
+ return ReplyAndPassAway (GetHTTPINTERNALERROR (" text/plain " , " no Result or Status " ), " internal error " );
218
214
}
219
215
}
220
-
221
-
222
- void HandleTimeout () {
223
- ReplyAndPassAway (Viewer->GetHTTPGATEWAYTIMEOUT (Event->Get ()));
224
- }
225
-
226
- void ReplyAndPassAway (TString data) {
227
- Send (Event->Sender , new NMon::TEvHttpInfoRes (data, 0 , NMon::IEvHttpInfoRes::EContentType::Custom));
228
- PassAway ();
229
- }
230
216
};
231
217
232
-
233
- }
234
- }
218
+ } // namespace NKikimr::NViewer
0 commit comments