From 6543a78d848d4bedc024af34a4f94dc58cb4a105 Mon Sep 17 00:00:00 2001 From: StekPerepolnen Date: Thu, 22 Feb 2024 10:00:30 +0000 Subject: [PATCH] added CORS support to viewer handlers --- ydb/core/viewer/counters_hosts.h | 8 +++++--- ydb/core/viewer/json_acl.h | 2 +- ydb/core/viewer/json_describe.h | 2 +- ydb/core/viewer/json_healthcheck.h | 18 ++++++++++-------- ydb/core/viewer/json_hotkeys.h | 2 +- ydb/core/viewer/json_local_rpc.h | 6 +++--- ydb/core/viewer/viewer.cpp | 28 ++++++++++++++++++++++++++++ ydb/core/viewer/viewer.h | 8 ++------ 8 files changed, 51 insertions(+), 23 deletions(-) diff --git a/ydb/core/viewer/counters_hosts.h b/ydb/core/viewer/counters_hosts.h index 55a2cc89a78b..9a65349aae2d 100644 --- a/ydb/core/viewer/counters_hosts.h +++ b/ydb/core/viewer/counters_hosts.h @@ -16,6 +16,7 @@ using namespace NActors; using namespace NNodeWhiteboard; class TCountersHostsList : public TActorBootstrapped { + IViewer* Viewer; NMon::TEvHttpInfo::TPtr Event; THolder NodesInfo; TMap> NodesResponses; @@ -29,8 +30,9 @@ class TCountersHostsList : public TActorBootstrapped { return NKikimrServices::TActivity::VIEWER_HANDLER; } - TCountersHostsList(IViewer*, NMon::TEvHttpInfo::TPtr& ev) - : Event(ev) + TCountersHostsList(IViewer* viewer, NMon::TEvHttpInfo::TPtr& ev) + : Viewer(viewer) + , Event(ev) {} void Bootstrap(const TActorContext& ctx) { @@ -145,7 +147,7 @@ class TCountersHostsList : public TActorBootstrapped { } } } - ctx.Send(Event->Sender, new NMon::TEvHttpInfoRes(HTTPOKTEXT + text.Str(), 0, NMon::IEvHttpInfoRes::EContentType::Custom)); + ctx.Send(Event->Sender, new NMon::TEvHttpInfoRes(Viewer->GetHTTPOKTEXT(Event->Get()) + text.Str(), 0, NMon::IEvHttpInfoRes::EContentType::Custom)); Die(ctx); } diff --git a/ydb/core/viewer/json_acl.h b/ydb/core/viewer/json_acl.h index d12df854f2f8..c18aff601294 100644 --- a/ydb/core/viewer/json_acl.h +++ b/ydb/core/viewer/json_acl.h @@ -155,7 +155,7 @@ class TJsonACL : public TViewerPipeClient { switch (DescribeResult->GetRecord().GetStatus()) { case NKikimrScheme::StatusAccessDenied: - headers = HTTPFORBIDDENJSON; + headers = Viewer->GetHTTPFORBIDDEN(Event->Get()); break; default: break; diff --git a/ydb/core/viewer/json_describe.h b/ydb/core/viewer/json_describe.h index 36a03a8daca4..709a7e62d2f6 100644 --- a/ydb/core/viewer/json_describe.h +++ b/ydb/core/viewer/json_describe.h @@ -265,7 +265,7 @@ class TJsonDescribe : public TViewerPipeClient { const auto *descriptor = NKikimrScheme::EStatus_descriptor(); auto accessDeniedStatus = descriptor->FindValueByNumber(NKikimrScheme::StatusAccessDenied)->name(); if (DescribeResult->GetStatus() == accessDeniedStatus) { - headers = HTTPFORBIDDENJSON; + headers = Viewer->GetHTTPFORBIDDEN(Event->Get()); } TProtoToJson::ProtoToJson(json, *DescribeResult, JsonSettings); } else { diff --git a/ydb/core/viewer/json_healthcheck.h b/ydb/core/viewer/json_healthcheck.h index fd55e460f620..67c62469cfae 100644 --- a/ydb/core/viewer/json_healthcheck.h +++ b/ydb/core/viewer/json_healthcheck.h @@ -24,6 +24,7 @@ enum HealthCheckResponseFormat { }; class TJsonHealthCheck : public TActorBootstrapped { + IViewer* Viewer; static const bool WithRetry = false; NMon::TEvHttpInfo::TPtr Event; TJsonSettings JsonSettings; @@ -36,8 +37,9 @@ class TJsonHealthCheck : public TActorBootstrapped { return NKikimrServices::TActivity::VIEWER_HANDLER; } - TJsonHealthCheck(IViewer*, NMon::TEvHttpInfo::TPtr& ev) - : Event(ev) + TJsonHealthCheck(IViewer* viewer, NMon::TEvHttpInfo::TPtr& ev) + : Viewer(viewer) + , Event(ev) {} void Bootstrap(const TActorContext& ctx) { @@ -78,7 +80,7 @@ class TJsonHealthCheck : public TActorBootstrapped { if (Ydb::Monitoring::StatusFlag_Status_Parse(params.Get("min_status"), &minStatus)) { request->Request.set_minimum_status(minStatus); } else { - Send(Event->Sender, new NMon::TEvHttpInfoRes(HTTPBADREQUEST, 0, NMon::IEvHttpInfoRes::EContentType::Custom)); + Send(Event->Sender, new NMon::TEvHttpInfoRes(Viewer->GetHTTPBADREQUEST(Event->Get()), 0, NMon::IEvHttpInfoRes::EContentType::Custom)); return PassAway(); } } @@ -104,7 +106,7 @@ class TJsonHealthCheck : public TActorBootstrapped { THashMap recordCounters; for (auto& log : ev->Get()->Result.issue_log()) { TMetricRecord record { - .Database = log.location().database().name(), + .Database = log.location().database().name(), .Message = log.message(), .Status = descriptor->FindValueByNumber(log.status())->name(), .Type = log.type() @@ -124,7 +126,7 @@ class TJsonHealthCheck : public TActorBootstrapped { void HandleJSON(NHealthCheck::TEvSelfCheckResult::TPtr& ev, const TActorContext &ctx) { TStringStream json; TProtoToJson::ProtoToJson(json, ev->Get()->Result, JsonSettings); - ctx.Send(Event->Sender, new NMon::TEvHttpInfoRes(HTTPOKJSON + json.Str(), 0, NMon::IEvHttpInfoRes::EContentType::Custom)); + ctx.Send(Event->Sender, new NMon::TEvHttpInfoRes(Viewer->GetHTTPOKJSON(Event->Get()) + json.Str(), 0, NMon::IEvHttpInfoRes::EContentType::Custom)); Die(ctx); } @@ -134,7 +136,7 @@ class TJsonHealthCheck : public TActorBootstrapped { TStringStream ss; IMetricEncoderPtr encoder = EncoderPrometheus(&ss); IMetricEncoder* e = encoder.Get(); - + TIntrusivePtr domains = AppData()->DomainsInfo; TIntrusivePtr domain = domains->Domains.begin()->second; auto filterDatabase = Database ? Database : "/" + domain->Name; @@ -173,7 +175,7 @@ class TJsonHealthCheck : public TActorBootstrapped { e->OnMetricEnd(); e->OnStreamEnd(); - ctx.Send(Event->Sender, new NMon::TEvHttpInfoRes(HTTPOKTEXT + ss.Str(), 0, NMon::IEvHttpInfoRes::EContentType::Custom)); + ctx.Send(Event->Sender, new NMon::TEvHttpInfoRes(Viewer->GetHTTPOKTEXT(Event->Get()) + ss.Str(), 0, NMon::IEvHttpInfoRes::EContentType::Custom)); Die(ctx); } @@ -186,7 +188,7 @@ class TJsonHealthCheck : public TActorBootstrapped { } void HandleTimeout(const TActorContext &ctx) { - Send(Event->Sender, new NMon::TEvHttpInfoRes(HTTPGATEWAYTIMEOUT, 0, NMon::IEvHttpInfoRes::EContentType::Custom)); + Send(Event->Sender, new NMon::TEvHttpInfoRes(Viewer->GetHTTPGATEWAYTIMEOUT(Event->Get()), 0, NMon::IEvHttpInfoRes::EContentType::Custom)); Die(ctx); } }; diff --git a/ydb/core/viewer/json_hotkeys.h b/ydb/core/viewer/json_hotkeys.h index 0aad63c9ed44..92e4b7e2a7ce 100644 --- a/ydb/core/viewer/json_hotkeys.h +++ b/ydb/core/viewer/json_hotkeys.h @@ -143,7 +143,7 @@ class TJsonHotkeys : public TViewerPipeClient { if (DescribeResult != nullptr) { switch (DescribeResult->GetRecord().GetStatus()) { case NKikimrScheme::StatusAccessDenied: - headers = HTTPFORBIDDENJSON; + headers = Viewer->GetHTTPFORBIDDEN(Event->Get()); break; default: break; diff --git a/ydb/core/viewer/json_local_rpc.h b/ydb/core/viewer/json_local_rpc.h index 6e3c54e4c516..b15a3ce88501 100644 --- a/ydb/core/viewer/json_local_rpc.h +++ b/ydb/core/viewer/json_local_rpc.h @@ -131,7 +131,7 @@ class TJsonLocalRpc : public TActorBootstrappedSender, new NMon::TEvHttpInfoRes(HTTPBADREQUEST, 0, NMon::IEvHttpInfoRes::EContentType::Custom)); + Send(Event->Sender, new NMon::TEvHttpInfoRes(Viewer->GetHTTPBADREQUEST(Event->Get(), {}, "Bad Request"), 0, NMon::IEvHttpInfoRes::EContentType::Custom)); PassAway(); } } else { @@ -195,9 +195,9 @@ class TJsonLocalRpc : public TActorBootstrappedGetHTTPOKJSON(Event->Get()); if (DescribeResult) { if (!DescribeResult->Status->IsSuccess()) { - headers = HTTPBADREQUEST; + headers = Viewer->GetHTTPBADREQUEST(Event->Get(), {}, "Bad Request"); if (DescribeResult->Status->GetStatus() == NYdb::EStatus::UNAUTHORIZED) { - headers = HTTPFORBIDDENJSON; + headers = Viewer->GetHTTPFORBIDDEN(Event->Get()); } } else { TProtoToJson::ProtoToJson(json, *(DescribeResult->Message), JsonSettings); diff --git a/ydb/core/viewer/viewer.cpp b/ydb/core/viewer/viewer.cpp index 65279dd2cbeb..42f71ad27ddb 100644 --- a/ydb/core/viewer/viewer.cpp +++ b/ydb/core/viewer/viewer.cpp @@ -152,9 +152,11 @@ class TViewer : public TActorBootstrapped, public IViewer { TString GetCORS(const NMon::TEvHttpInfo* request) override; TString GetHTTPOKJSON(const NMon::TEvHttpInfo* request, TString response) override; + TString GetHTTPOKTEXT(const NMon::TEvHttpInfo* request, TString response) override; TString GetHTTPOK(const NMon::TEvHttpInfo* request, TString type, TString response) override; TString GetHTTPGATEWAYTIMEOUT(const NMon::TEvHttpInfo* request) override; TString GetHTTPBADREQUEST(const NMon::TEvHttpInfo* request, TString type, TString response) override; + TString GetHTTPFORBIDDEN(const NMon::TEvHttpInfo* request) override; void RegisterVirtualHandler( NKikimrViewer::EObjectType parentObjectType, @@ -467,6 +469,22 @@ TString TViewer::GetHTTPOKJSON(const NMon::TEvHttpInfo* request, TString respons return res; } +TString TViewer::GetHTTPOKTEXT(const NMon::TEvHttpInfo* request, TString response) { + TStringBuilder res; + res << "HTTP/1.1 200 Ok\r\n" + << "Content-Type: text/plain; charset=utf-8\r\n" + << "X-Worker-Name: " << CurrentWorkerName << "\r\n"; + res << GetCORS(request); + if (response) { + res << "Content-Length: " << response.size() << "\r\n"; + } + res << "\r\n"; + if (response) { + res << response; + } + return res; +} + TString TViewer::GetHTTPGATEWAYTIMEOUT(const NMon::TEvHttpInfo* request) { TStringBuilder res; res << "HTTP/1.1 504 Gateway Time-out\r\n" @@ -492,6 +510,16 @@ TString TViewer::GetHTTPBADREQUEST(const NMon::TEvHttpInfo* request, TString con return res; } +TString TViewer::GetHTTPFORBIDDEN(const NMon::TEvHttpInfo* request) { + TStringBuilder res; + res << "HTTP/1.1 403 Forbidden\r\n" + << "Content-Type: application/json; charset=utf-8\r\n" + << "Connection: Close\r\n"; + res << GetCORS(request); + res << "\r\n"; + return res; +} + TString TViewer::GetHTTPOK(const NMon::TEvHttpInfo* request, TString contentType = {}, TString response = {}) { TStringBuilder res; res << "HTTP/1.1 200 Ok\r\n" diff --git a/ydb/core/viewer/viewer.h b/ydb/core/viewer/viewer.h index 7fdab30f8332..fd58e6d8f535 100644 --- a/ydb/core/viewer/viewer.h +++ b/ydb/core/viewer/viewer.h @@ -156,8 +156,10 @@ class IViewer { virtual TString GetCORS(const NMon::TEvHttpInfo* request) = 0; virtual TString GetHTTPOK(const NMon::TEvHttpInfo* request, TString contentType = {}, TString response = {}) = 0; virtual TString GetHTTPOKJSON(const NMon::TEvHttpInfo* request, TString response = {}) = 0; + virtual TString GetHTTPOKTEXT(const NMon::TEvHttpInfo* request, TString response = {}) = 0; virtual TString GetHTTPGATEWAYTIMEOUT(const NMon::TEvHttpInfo* request) = 0; virtual TString GetHTTPBADREQUEST(const NMon::TEvHttpInfo* request, TString contentType = {}, TString response = {}) = 0; + virtual TString GetHTTPFORBIDDEN(const NMon::TEvHttpInfo* request) = 0; }; void SetupPQVirtualHandlers(IViewer* viewer); @@ -184,12 +186,6 @@ struct TJsonRequestParameters { static TString GetParameters() { return TString(); } }; -static const char HTTPOKJSON[] = "HTTP/1.1 200 Ok\r\nAccess-Control-Allow-Origin: *\r\nContent-Type: application/json; charset=utf-8\r\nConnection: Close\r\n\r\n"; -static const char HTTPOKTEXT[] = "HTTP/1.1 200 Ok\r\nAccess-Control-Allow-Origin: *\r\nContent-Type: text/plain; charset=utf-8\r\nConnection: Close\r\n\r\n"; -static const char HTTPFORBIDDENJSON[] = "HTTP/1.1 403 Forbidden\r\nAccess-Control-Allow-Origin: *\r\nContent-Type: application/json; charset=utf-8\r\nConnection: Close\r\n\r\n"; -static const char HTTPGATEWAYTIMEOUT[] = "HTTP/1.1 504 Gateway Time-out\r\nConnection: Close\r\n\r\nGateway Time-out\r\n"; -static const char HTTPBADREQUEST[] = "HTTP/1.1 400 Bad Request\r\nConnection: Close\r\n\r\nBad Request\r\n"; - template void GenericSplitIds(TStringBuf source, char delim, OutputIteratorType it) { for (TStringBuf value = source.NextTok(delim); !value.empty(); value = source.NextTok(delim)) {