Dump configs on BE's website '/varz' Change NAVIGATION_BAR_PREFIX from 'Impala' to 'Doris' Format the related files by clang-format
167 lines
5.5 KiB
C++
167 lines
5.5 KiB
C++
// Licensed to the Apache Software Foundation (ASF) under one
|
|
// or more contributor license agreements. See the NOTICE file
|
|
// distributed with this work for additional information
|
|
// regarding copyright ownership. The ASF licenses this file
|
|
// to you under the Apache License, Version 2.0 (the
|
|
// "License"); you may not use this file except in compliance
|
|
// with the License. You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing,
|
|
// software distributed under the License is distributed on an
|
|
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
// KIND, either express or implied. See the License for the
|
|
// specific language governing permissions and limitations
|
|
// under the License.
|
|
|
|
#include "http/web_page_handler.h"
|
|
|
|
#include <boost/bind.hpp>
|
|
#include <boost/mem_fn.hpp>
|
|
|
|
#include "http/ev_http_server.h"
|
|
#include "http/http_channel.h"
|
|
#include "http/http_headers.h"
|
|
#include "http/http_request.h"
|
|
#include "http/http_response.h"
|
|
#include "http/http_status.h"
|
|
#include "util/cpu_info.h"
|
|
#include "util/debug_util.h"
|
|
#include "util/disk_info.h"
|
|
#include "util/mem_info.h"
|
|
|
|
namespace doris {
|
|
|
|
static std::string s_html_content_type = "text/html";
|
|
|
|
WebPageHandler::WebPageHandler(EvHttpServer* server) : _http_server(server) {
|
|
PageHandlerCallback default_callback =
|
|
boost::bind<void>(boost::mem_fn(&WebPageHandler::root_handler), this, _1, _2);
|
|
register_page("/", default_callback);
|
|
}
|
|
|
|
void WebPageHandler::register_page(const std::string& path, const PageHandlerCallback& callback) {
|
|
// Put this handler to to s_handler_by_name
|
|
// because handler does't often new
|
|
// So we insert it to this set when everytime
|
|
boost::mutex::scoped_lock lock(_map_lock);
|
|
auto map_iter = _page_map.find(path);
|
|
if (map_iter == _page_map.end()) {
|
|
// first time, register this to web server
|
|
_http_server->register_handler(HttpMethod::GET, path, this);
|
|
}
|
|
_page_map[path].add_callback(callback);
|
|
}
|
|
|
|
void WebPageHandler::handle(HttpRequest* req) {
|
|
// Should we render with css styles?
|
|
bool use_style = true;
|
|
auto& params = *req->params();
|
|
if (params.find("raw") != params.end()) {
|
|
use_style = false;
|
|
}
|
|
|
|
std::stringstream output;
|
|
|
|
// Append header
|
|
if (use_style) {
|
|
bootstrap_page_header(&output);
|
|
}
|
|
|
|
// Append content
|
|
// push_content(&output);
|
|
LOG(INFO) << req->debug_string();
|
|
{
|
|
boost::mutex::scoped_lock lock(_map_lock);
|
|
auto iter = _page_map.find(req->raw_path());
|
|
if (iter != _page_map.end()) {
|
|
for (auto& callback : iter->second.callbacks()) {
|
|
callback(*req->params(), &output);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Append footer
|
|
if (use_style) {
|
|
bootstrap_page_footer(&output);
|
|
}
|
|
std::string str = output.str();
|
|
|
|
req->add_output_header(HttpHeaders::CONTENT_TYPE, s_html_content_type.c_str());
|
|
HttpChannel::send_reply(req, HttpStatus::OK, str);
|
|
#if 0
|
|
HttpResponse response(HttpStatus::OK, s_html_content_type, &str);
|
|
channel->send_response(response);
|
|
#endif
|
|
}
|
|
|
|
static const std::string PAGE_HEADER =
|
|
"<!DOCTYPE html>"
|
|
" <html>"
|
|
" <head><title>Doris</title>"
|
|
" <link href='www/bootstrap/css/bootstrap.min.css' rel='stylesheet' media='screen'>"
|
|
" <style>"
|
|
" body {"
|
|
" padding-top: 60px; "
|
|
" }"
|
|
" </style>"
|
|
" </head>"
|
|
" <body>";
|
|
|
|
static const std::string PAGE_FOOTER = "</div></body></html>";
|
|
|
|
static const std::string NAVIGATION_BAR_PREFIX =
|
|
"<div class='navbar navbar-inverse navbar-fixed-top'>"
|
|
" <div class='navbar-inner'>"
|
|
" <div class='container'>"
|
|
" <a class='btn btn-navbar' data-toggle='collapse' data-target='.nav-collapse'>"
|
|
" <span class='icon-bar'></span>"
|
|
" <span class='icon-bar'></span>"
|
|
" <span class='icon-bar'></span>"
|
|
" </a>"
|
|
" <a class='brand' href='/'>Doris</a>"
|
|
" <div class='nav-collapse collapse'>"
|
|
" <ul class='nav'>";
|
|
|
|
static const std::string NAVIGATION_BAR_SUFFIX =
|
|
" </ul>"
|
|
" </div>"
|
|
" </div>"
|
|
" </div>"
|
|
" </div>"
|
|
" <div class='container'>";
|
|
|
|
void WebPageHandler::bootstrap_page_header(std::stringstream* output) {
|
|
boost::mutex::scoped_lock lock(_map_lock);
|
|
(*output) << PAGE_HEADER;
|
|
(*output) << NAVIGATION_BAR_PREFIX;
|
|
for (auto& iter : _page_map) {
|
|
(*output) << "<li><a href=\"" << iter.first << "\">" << iter.first << "</a></li>";
|
|
}
|
|
(*output) << NAVIGATION_BAR_SUFFIX;
|
|
}
|
|
|
|
void WebPageHandler::bootstrap_page_footer(std::stringstream* output) {
|
|
(*output) << PAGE_FOOTER;
|
|
}
|
|
|
|
void WebPageHandler::root_handler(const ArgumentMap& args, std::stringstream* output) {
|
|
// _path_handler_lock already held by MongooseCallback
|
|
(*output) << "<h2>Version</h2>";
|
|
(*output) << "<pre>" << get_version_string(false) << "</pre>" << std::endl;
|
|
(*output) << "<h2>Hardware Info</h2>";
|
|
(*output) << "<pre>";
|
|
(*output) << CpuInfo::debug_string();
|
|
(*output) << MemInfo::debug_string();
|
|
(*output) << DiskInfo::debug_string();
|
|
(*output) << "</pre>";
|
|
|
|
(*output) << "<h2>Status Pages</h2>";
|
|
for (auto& iter : _page_map) {
|
|
(*output) << "<a href=\"" << iter.first << "\">" << iter.first << "</a><br/>";
|
|
}
|
|
}
|
|
|
|
} // namespace doris
|