// 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 #include #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(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 = "" " " " Doris" " " " " " " " "; static const std::string PAGE_FOOTER = ""; static const std::string NAVIGATION_BAR_PREFIX = "" "
"; 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) << "
  • " << iter.first << "
  • "; } (*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) << "

    Version

    "; (*output) << "
    " << get_version_string(false) << "
    " << std::endl; (*output) << "

    Hardware Info

    "; (*output) << "
    ";
        (*output) << CpuInfo::debug_string();
        (*output) << MemInfo::debug_string();
        (*output) << DiskInfo::debug_string();
        (*output) << "
    "; (*output) << "

    Status Pages

    "; for (auto& iter : _page_map) { (*output) << "" << iter.first << "
    "; } } } // namespace doris