aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Efimov <xeno@ydb.tech>2025-05-23 11:14:06 +0700
committerGitHub <noreply@github.com>2025-05-23 11:14:06 +0700
commit8309fbe29b9bccd50769803fc993deac18cd7c2d (patch)
tree6dbba831870fc3aae010f9aaca387f0571872bc4
parent0e4d027cd6d5b101b6237440de440014625614e5 (diff)
downloadydb-8309fbe29b9bccd50769803fc993deac18cd7c2d.tar.gz
support form-urlencoded in base class (#18675)
-rw-r--r--ydb/core/viewer/json_pipe_req.cpp17
-rw-r--r--ydb/core/viewer/json_pipe_req.h1
-rw-r--r--ydb/core/viewer/viewer_render.h144
-rw-r--r--ydb/core/viewer/viewer_request.cpp2
4 files changed, 65 insertions, 99 deletions
diff --git a/ydb/core/viewer/json_pipe_req.cpp b/ydb/core/viewer/json_pipe_req.cpp
index 8a7ff5ecc34..822e29f7bb6 100644
--- a/ydb/core/viewer/json_pipe_req.cpp
+++ b/ydb/core/viewer/json_pipe_req.cpp
@@ -143,6 +143,11 @@ void TViewerPipeClient::BuildParamsFromJson(TStringBuf data) {
case NJson::EJsonValueType::JSON_BOOLEAN:
Params.InsertUnescaped(key, value.GetStringRobust());
break;
+ case NJson::EJsonValueType::JSON_ARRAY:
+ for (const auto& item : value.GetArray()) {
+ Params.InsertUnescaped(key, item.GetStringRobust());
+ }
+ break;
default:
break;
}
@@ -152,6 +157,12 @@ void TViewerPipeClient::BuildParamsFromJson(TStringBuf data) {
}
}
+void TViewerPipeClient::BuildParamsFromFormData(TStringBuf data) {
+ for (const auto& [key, value] : TCgiParameters(data)) {
+ Params.InsertUnescaped(key, value);
+ }
+}
+
void TViewerPipeClient::SetupTracing(const TString& handlerName) {
auto request = GetRequest();
NWilson::TTraceId traceId;
@@ -191,6 +202,9 @@ TViewerPipeClient::TViewerPipeClient(IViewer* viewer, NMon::TEvHttpInfo::TPtr& e
if (NHttp::Trim(Event->Get()->Request.GetHeader("Content-Type").Before(';'), ' ') == "application/json") {
BuildParamsFromJson(Event->Get()->Request.GetPostContent());
}
+ if (NHttp::Trim(Event->Get()->Request.GetHeader("Content-Type").Before(';'), ' ') == "application/x-www-form-urlencoded") {
+ BuildParamsFromFormData(Event->Get()->Request.GetPostContent());
+ }
InitConfig(Params);
SetupTracing(handlerName);
}
@@ -204,6 +218,9 @@ TViewerPipeClient::TViewerPipeClient(IViewer* viewer, NHttp::TEvHttpProxy::TEvHt
if (NHttp::Trim(headers.Get("Content-Type").Before(';'), ' ') == "application/json") {
BuildParamsFromJson(HttpEvent->Get()->Request->Body);
}
+ if (NHttp::Trim(headers.Get("Content-Type").Before(';'), ' ') == "application/x-www-form-urlencoded") {
+ BuildParamsFromFormData(HttpEvent->Get()->Request->Body);
+ }
InitConfig(Params);
SetupTracing(handlerName);
}
diff --git a/ydb/core/viewer/json_pipe_req.h b/ydb/core/viewer/json_pipe_req.h
index 3910c85244e..fc5fe76da7c 100644
--- a/ydb/core/viewer/json_pipe_req.h
+++ b/ydb/core/viewer/json_pipe_req.h
@@ -332,6 +332,7 @@ protected:
void InitConfig(const TCgiParameters& params);
void InitConfig(const TRequestSettings& settings);
void BuildParamsFromJson(TStringBuf data);
+ void BuildParamsFromFormData(TStringBuf data);
void SetupTracing(const TString& handlerName);
template<typename TJson>
diff --git a/ydb/core/viewer/viewer_render.h b/ydb/core/viewer/viewer_render.h
index 44aea71caff..8d3532c13b2 100644
--- a/ydb/core/viewer/viewer_render.h
+++ b/ydb/core/viewer/viewer_render.h
@@ -14,62 +14,38 @@ using namespace NMonitoring;
class TJsonRender : public TViewerPipeClient {
using TThis = TJsonRender;
using TBase = TViewerPipeClient;
- TEvViewer::TEvViewerRequest::TPtr ViewerRequest;
- ui32 Timeout = 0;
+ using TBase::ReplyAndPassAway;
std::vector<TString> Metrics;
- TCgiParameters Params;
public:
TJsonRender(IViewer* viewer, NMon::TEvHttpInfo::TPtr& ev)
: TViewerPipeClient(viewer, ev)
{
- const auto& params(Event->Get()->Request.GetParams());
-
- InitConfig(params);
- Timeout = FromStringWithDefault<ui32>(params.Get("timeout"), 30000);
- }
-
- TJsonRender(TEvViewer::TEvViewerRequest::TPtr& ev)
- : ViewerRequest(ev)
- {
- auto& request = ViewerRequest->Get()->Record.GetRenderRequest();
-
- TCgiParameters params(request.GetUri());
- InitConfig(params);
- Direct = true;
- Timeout = ViewerRequest->Get()->Record.GetTimeout();
}
void Bootstrap() override {
if (NeedToRedirect()) {
return;
}
- auto postData = Event
- ? Event->Get()->Request.GetPostContent()
- : ViewerRequest->Get()->Record.GetRenderRequest().GetContent();
- BLOG_D("PostData=" << postData);
NKikimrGraph::TEvGetMetrics getRequest;
- if (postData) {
- Params = TCgiParameters(postData);
- if (Params.Has("target")) {
- TString metric;
- size_t num = 0;
- for (;;) {
- metric = Params.Get("target", num);
- if (metric.empty()) {
- break;
- }
- Metrics.push_back(metric);
- ++num;
+ if (Params.Has("target")) {
+ TString metric;
+ size_t num = 0;
+ for (;;) {
+ metric = Params.Get("target", num);
+ if (metric.empty()) {
+ break;
}
+ Metrics.push_back(metric);
+ ++num;
}
SendGraphRequest();
} else {
- ReplyAndPassAway(Viewer->GetHTTPBADREQUEST(Event->Get(), {}, "Bad Request"));
+ ReplyAndPassAway(GetHTTPBADREQUEST("text/plain", "Bad Request"));
return;
}
- Become(&TThis::StateWork, TDuration::MilliSeconds(Timeout), new TEvents::TEvWakeup());
+ Become(&TThis::StateWork, Timeout, new TEvents::TEvWakeup());
}
STATEFN(StateWork) {
@@ -90,7 +66,7 @@ public:
"\x03\x00\x00\x00\x25\xdb\x56\xca\x00\x00\x00\x03\x50\x4c\x54\x45\x00\x00\x00\xa7\x7a\x3d\xda\x00\x00"
"\x00\x01\x74\x52\x4e\x53\x00\x40\xe6\xd8\x66\x00\x00\x00\x0a\x49\x44\x41\x54\x08\xd7\x63\x60\x00\x00"
"\x00\x02\x00\x01\xe2\x21\xbc\x33\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82";
- Send(Event->Sender, new NMon::TEvHttpInfoRes(Viewer->GetHTTPOK(Event->Get(), "image/png", png1x1), 0, NMon::IEvHttpInfoRes::EContentType::Custom));
+ ReplyAndPassAway(GetHTTPOK("image/png", png1x1));
return PassAway();
}
if (Params.Has("from")) {
@@ -106,82 +82,56 @@ public:
}
void HandleRenderResponse(NKikimrGraph::TEvMetricsResult& response) {
- if (Event) {
- NJson::TJsonValue json;
+ NJson::TJsonValue json;
- if (response.GetError()) {
- json["status"] = "error";
- json["error"] = response.GetError();
- return ReplyAndPassAway(GetHTTPOKJSON(json));
- }
- if (response.DataSize() != Metrics.size()) {
+ if (response.GetError()) {
+ json["status"] = "error";
+ json["error"] = response.GetError();
+ return ReplyAndPassAway(GetHTTPOKJSON(json));
+ }
+ if (response.DataSize() != Metrics.size()) {
+ json["status"] = "error";
+ json["error"] = "Invalid data size received";
+ return ReplyAndPassAway(GetHTTPOKJSON(json));
+ }
+ for (size_t nMetric = 0; nMetric < response.DataSize(); ++nMetric) {
+ const auto& protoMetric(response.GetData(nMetric));
+ if (response.TimeSize() != protoMetric.ValuesSize()) {
json["status"] = "error";
- json["error"] = "Invalid data size received";
+ json["error"] = "Invalid value size received";
return ReplyAndPassAway(GetHTTPOKJSON(json));
}
+ }
+ { // graphite
+ json.SetType(NJson::JSON_ARRAY);
for (size_t nMetric = 0; nMetric < response.DataSize(); ++nMetric) {
const auto& protoMetric(response.GetData(nMetric));
- if (response.TimeSize() != protoMetric.ValuesSize()) {
- json["status"] = "error";
- json["error"] = "Invalid value size received";
- return ReplyAndPassAway(GetHTTPOKJSON(json));
- }
- }
- { // graphite
- json.SetType(NJson::JSON_ARRAY);
- for (size_t nMetric = 0; nMetric < response.DataSize(); ++nMetric) {
- const auto& protoMetric(response.GetData(nMetric));
- NJson::TJsonValue& jsonMetric(json.AppendValue({}));
- jsonMetric["target"] = Metrics[nMetric];
- jsonMetric["title"] = Metrics[nMetric];
- jsonMetric["tags"]["name"] = Metrics[nMetric];
- NJson::TJsonValue& jsonDataPoints(jsonMetric["datapoints"]);
- jsonDataPoints.SetType(NJson::JSON_ARRAY);
- for (size_t nTime = 0; nTime < response.TimeSize(); ++nTime) {
- NJson::TJsonValue& jsonDataPoint(jsonDataPoints.AppendValue({}));
- double value = protoMetric.GetValues(nTime);
- if (isnan(value)) {
- jsonDataPoint.AppendValue(NJson::TJsonValue(NJson::JSON_NULL));
- } else {
- jsonDataPoint.AppendValue(value);
- }
- jsonDataPoint.AppendValue(response.GetTime(nTime));
+ NJson::TJsonValue& jsonMetric(json.AppendValue({}));
+ jsonMetric["target"] = Metrics[nMetric];
+ jsonMetric["title"] = Metrics[nMetric];
+ jsonMetric["tags"]["name"] = Metrics[nMetric];
+ NJson::TJsonValue& jsonDataPoints(jsonMetric["datapoints"]);
+ jsonDataPoints.SetType(NJson::JSON_ARRAY);
+ for (size_t nTime = 0; nTime < response.TimeSize(); ++nTime) {
+ NJson::TJsonValue& jsonDataPoint(jsonDataPoints.AppendValue({}));
+ double value = protoMetric.GetValues(nTime);
+ if (isnan(value)) {
+ jsonDataPoint.AppendValue(NJson::TJsonValue(NJson::JSON_NULL));
+ } else {
+ jsonDataPoint.AppendValue(value);
}
+ jsonDataPoint.AppendValue(response.GetTime(nTime));
}
}
-
- ReplyAndPassAway(GetHTTPOKJSON(json));
- } else {
- TEvViewer::TEvViewerResponse* viewerResponse = new TEvViewer::TEvViewerResponse();
- viewerResponse->Record.MutableRenderResponse()->CopyFrom(response);
- ReplyAndPassAway(viewerResponse);
}
+
+ ReplyAndPassAway(GetHTTPOKJSON(json));
}
void Handle(NGraph::TEvGraph::TEvMetricsResult::TPtr& ev) {
HandleRenderResponse(ev->Get()->Record);
}
- void HandleTimeout() {
- if (Event) {
- ReplyAndPassAway(Viewer->GetHTTPGATEWAYTIMEOUT(Event->Get()));
- } else {
- auto* response = new TEvViewer::TEvViewerResponse();
- response->Record.MutableRenderResponse()->SetError("Request timed out");
- ReplyAndPassAway(response);
- }
- }
-
- void ReplyAndPassAway(TEvViewer::TEvViewerResponse* response) {
- Send(ViewerRequest->Sender, response);
- PassAway();
- }
-
- void ReplyAndPassAway(TString data) {
- Send(Event->Sender, new NMon::TEvHttpInfoRes(std::move(data), 0, NMon::IEvHttpInfoRes::EContentType::Custom));
- PassAway();
- }
-
void ReplyAndPassAway() override {
}
diff --git a/ydb/core/viewer/viewer_request.cpp b/ydb/core/viewer/viewer_request.cpp
index 1afcbfc69a5..357fdae9ab1 100644
--- a/ydb/core/viewer/viewer_request.cpp
+++ b/ydb/core/viewer/viewer_request.cpp
@@ -124,8 +124,6 @@ IActor* CreateViewerRequestHandler(TEvViewer::TEvViewerRequest::TPtr& request) {
return new TViewerWhiteboardRequest<TEvWhiteboard::TEvNodeStateRequest, TEvWhiteboard::TEvNodeStateResponse>(request);
case NKikimrViewer::TEvViewerRequest::kQueryRequest:
return new TJsonQueryOld(request);
- case NKikimrViewer::TEvViewerRequest::kRenderRequest:
- return new TJsonRender(request);
case NKikimrViewer::TEvViewerRequest::kAutocompleteRequest:
return new TJsonAutocomplete(request);
default: