diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2022-09-16 16:18:26 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-16 16:18:26 +0200 |
commit | c2a9a266f28545fe015f7d4e22afd4f9619e97db (patch) | |
tree | c997f10a9e1734ee0b795601a2399e8ff78b5294 | |
parent | 658dcaff63003a3d9797c3e78a51a5058206fe9f (diff) | |
parent | 5d665ecd1799d6a1b67a684b6f09f4c774f63a15 (diff) |
Merge pull request #24095 from vespa-engine/vekterli/allow-path-prefix-alias-for-legacy-status-pages
Allow path prefix alias for legacy content status pages [run-systemtest]
5 files changed, 60 insertions, 24 deletions
diff --git a/storage/src/tests/frameworkimpl/status/statustest.cpp b/storage/src/tests/frameworkimpl/status/statustest.cpp index 2593eabecec..0db5f2cf6b0 100644 --- a/storage/src/tests/frameworkimpl/status/statustest.cpp +++ b/storage/src/tests/frameworkimpl/status/statustest.cpp @@ -12,6 +12,7 @@ #include <vespa/config/subscription/configuri.h> #include <vespa/vespalib/gtest/gtest.h> #include <gmock/gmock.h> +#include <string> using namespace ::testing; @@ -99,6 +100,19 @@ void StatusTest::SetUp() { _node = std::make_unique<TestServiceLayerApp>(); } +namespace { + +std::string additional_fixed_http_response_headers() { + return ("X-XSS-Protection: 1; mode=block\r\n" + "X-Frame-Options: DENY\r\n" + "Content-Security-Policy: default-src 'none'; frame-ancestors 'none'\r\n" + "X-Content-Type-Options: nosniff\r\n" + "Cache-Control: no-store\r\n" + "Pragma: no-cache\r\n"); +} + +} + TEST_F(StatusTest, index_status_page) { StatusComponent rep1(_node->getComponentRegister(), "foo", new HtmlStatusReporter( @@ -115,12 +129,7 @@ TEST_F(StatusTest, index_status_page) { "Connection: close\r\n" "Content-Type: text\\/html\r\n" "Content-Length: [0-9]+\r\n" - "X-XSS-Protection: 1; mode=block\r\n" - "X-Frame-Options: DENY\r\n" - "Content-Security-Policy: default-src 'none'; frame-ancestors 'none'\r\n" - "X-Content-Type-Options: nosniff\r\n" - "Cache-Control: no-store\r\n" - "Pragma: no-cache\r\n" + + additional_fixed_http_response_headers() + "\r\n" "<html>\n" "<head>\n" @@ -150,12 +159,33 @@ TEST_F(StatusTest, html_status) { "Connection: close\r\n" "Content-Type: text/html\r\n" "Content-Length: 117\r\n" - "X-XSS-Protection: 1; mode=block\r\n" - "X-Frame-Options: DENY\r\n" - "Content-Security-Policy: default-src 'none'; frame-ancestors 'none'\r\n" - "X-Content-Type-Options: nosniff\r\n" - "Cache-Control: no-store\r\n" - "Pragma: no-cache\r\n" + + additional_fixed_http_response_headers() + + "\r\n" + "<html>\n" + "<head>\n" + " <title>Foo impl</title>\n" + "<!-- script --></head>\n" + "<body>\n" + " <h1>Foo impl</h1>\n" + "<p>info</p></body>\n" + "</html>\n" + ); + EXPECT_EQ(expected, std::string(actual)); +} + +TEST_F(StatusTest, path_with_v1_prefix_aliases_to_handler_under_root) { + StatusComponent rep1(_node->getComponentRegister(), "foo", + new HtmlStatusReporter("fooid", "Foo impl", "<p>info</p>", "<!-- script -->")); + StatusWebServer webServer(_node->getComponentRegister(), + _node->getComponentRegister(), + config::ConfigUri("raw:httpport 0")); + auto actual = fetch(webServer.getListenPort(), "/contentnode-status/v1/fooid?unusedParam"); + std::string expected( + "HTTP/1.1 200 OK\r\n" + "Connection: close\r\n" + "Content-Type: text/html\r\n" + "Content-Length: 117\r\n" + + additional_fixed_http_response_headers() + "\r\n" "<html>\n" "<head>\n" @@ -182,12 +212,7 @@ TEST_F(StatusTest, xml_sStatus) { "Connection: close\r\n" "Content-Type: application/xml\r\n" "Content-Length: 100\r\n" - "X-XSS-Protection: 1; mode=block\r\n" - "X-Frame-Options: DENY\r\n" - "Content-Security-Policy: default-src 'none'; frame-ancestors 'none'\r\n" - "X-Content-Type-Options: nosniff\r\n" - "Cache-Control: no-store\r\n" - "Pragma: no-cache\r\n" + + additional_fixed_http_response_headers() + "\r\n" "<?xml version=\"1.0\"?>\n" "<status id=\"fooid\" name=\"Foo impl\">\n" diff --git a/storage/src/vespa/storage/bucketdb/bucketmanager.cpp b/storage/src/vespa/storage/bucketdb/bucketmanager.cpp index 166bda1adbb..51422de07e6 100644 --- a/storage/src/vespa/storage/bucketdb/bucketmanager.cpp +++ b/storage/src/vespa/storage/bucketdb/bucketmanager.cpp @@ -376,8 +376,8 @@ BucketManager::reportStatus(std::ostream& out, } else { framework::PartlyHtmlStatusReporter htmlReporter(*this); htmlReporter.reportHtmlHeader(out, path); - // Print menu - out << "<font size=\"-1\">[ <a href=\"/\">Back to top</a>" + // Print menu + out << "<font size=\"-1\">[ <a href=\"../\">Back to top</a>" << " | <a href=\"?showall\">Show all buckets</a> ]</font>"; htmlReporter.reportHtmlFooter(out, path); } diff --git a/storage/src/vespa/storage/frameworkimpl/status/statuswebserver.cpp b/storage/src/vespa/storage/frameworkimpl/status/statuswebserver.cpp index 7139ab0eb41..b2bce8a1241 100644 --- a/storage/src/vespa/storage/frameworkimpl/status/statuswebserver.cpp +++ b/storage/src/vespa/storage/frameworkimpl/status/statuswebserver.cpp @@ -169,10 +169,21 @@ void StatusWebServer::handlePage(const framework::HttpUrlPath& urlpath, vespalib::Portal::GetRequest request) { vespalib::string link(urlpath.getPath()); - if (!link.empty() && link[0] == '/') link = link.substr(1); + + // We allow a fixed path prefix that aliases down to whatever is provided after the prefix. + vespalib::stringref optional_status_path_prefix = "/contentnode-status/v1/"; + if (link.starts_with(optional_status_path_prefix)) { + link = link.substr(optional_status_path_prefix.size()); + } + + if (!link.empty() && link[0] == '/') { + link = link.substr(1); + } size_t slashPos = link.find('/'); - if (slashPos != std::string::npos) link = link.substr(0, slashPos); + if (slashPos != std::string::npos) { + link = link.substr(0, slashPos); + } if ( ! link.empty()) { const framework::StatusReporter *reporter = _reporterMap.getStatusReporter(link); diff --git a/storage/src/vespa/storage/persistence/filestorage/filestormanager.cpp b/storage/src/vespa/storage/persistence/filestorage/filestormanager.cpp index 62be96447a4..314836384ce 100644 --- a/storage/src/vespa/storage/persistence/filestorage/filestormanager.cpp +++ b/storage/src/vespa/storage/persistence/filestorage/filestormanager.cpp @@ -893,7 +893,7 @@ FileStorManager::reportHtmlStatus(std::ostream& out, const framework::HttpUrlPat bool showStatus = !path.hasAttribute("thread"); bool verbose = path.hasAttribute("verbose"); // Print menu - out << "<font size=\"-1\">[ <a href=\"/\">Back to top</a>" + out << "<font size=\"-1\">[ <a href=\"../\">Back to top</a>" << " | <a href=\"?" << (verbose ? "verbose" : "") << "\">Main filestor manager status page</a>" << " | <a href=\"?" << (verbose ? "notverbose" : "verbose"); diff --git a/storage/src/vespa/storage/visiting/visitormanager.cpp b/storage/src/vespa/storage/visiting/visitormanager.cpp index b305abae019..759f1f1f059 100644 --- a/storage/src/vespa/storage/visiting/visitormanager.cpp +++ b/storage/src/vespa/storage/visiting/visitormanager.cpp @@ -566,7 +566,7 @@ VisitorManager::reportHtmlStatus(std::ostream& out, bool showAll = path.hasAttribute("allvisitors"); // Print menu - out << "<font size=\"-1\">[ <a href=\"/\">Back to top</a>" + out << "<font size=\"-1\">[ <a href=\"../\">Back to top</a>" << " | <a href=\"?" << (verbose ? "verbose" : "") << "\">Main visitor manager status page</a>" << " | <a href=\"?allvisitors" << (verbose ? "&verbose" : "") |