// 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 "kudu/server/webserver.h"

#include <netinet/in.h>
#include <openssl/crypto.h>
#include <sys/socket.h>

#include <algorithm>
#include <csignal>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <map>
#include <mutex>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#include <boost/algorithm/string/case_conv.hpp>
#include <gflags/gflags.h>
#include <glog/logging.h>
#include <mustache.h>
#include <squeasel.h>

#include "kudu/gutil/endian.h"
#include "kudu/gutil/macros.h"
#include "kudu/gutil/map-util.h"
#include "kudu/gutil/stl_util.h"
#include "kudu/gutil/strings/join.h"
#include "kudu/gutil/strings/numbers.h"
#include "kudu/gutil/strings/split.h"
#include "kudu/gutil/strings/stringpiece.h"
#include "kudu/gutil/strings/strip.h"
#include "kudu/gutil/strings/substitute.h"
#include "kudu/security/gssapi.h"
#include "kudu/util/easy_json.h"
#include "kudu/util/env.h"
#include "kudu/util/flag_tags.h"
#include "kudu/util/locks.h"
#include "kudu/util/logging.h"
#include "kudu/util/net/net_util.h"
#include "kudu/util/net/sockaddr.h"
#include "kudu/util/openssl_util.h"
#include "kudu/util/string_case.h"
#include "kudu/util/url-coding.h"
#include "kudu/util/version_info.h"
#include "kudu/util/zlib.h"

#if defined(__APPLE__)
typedef sig_t sighandler_t;
#endif

using mustache::RenderTemplate;
using std::ostringstream;
using std::pair;
using std::stringstream;
using std::string;
using std::unordered_set;
using std::vector;
using strings::Substitute;

DEFINE_int32(webserver_max_post_length_bytes, 1024 * 1024,
             "The maximum length of a POST request that will be accepted by "
             "the embedded web server.");
TAG_FLAG(webserver_max_post_length_bytes, advanced);
TAG_FLAG(webserver_max_post_length_bytes, runtime);

DEFINE_string(webserver_x_frame_options, "DENY",
              "The webserver will add an 'X-Frame-Options' HTTP header with this value "
              "to all responses. This can help prevent clickjacking attacks.");
TAG_FLAG(webserver_x_frame_options, advanced);

DEFINE_bool(webserver_enable_csp, true,
            "The webserver adds the Content-Security-Policy header to response when enabled.");
TAG_FLAG(webserver_enable_csp, advanced);
TAG_FLAG(webserver_enable_csp, runtime);


namespace kudu {

namespace {

// Last error message from the webserver.
// TODO(todd) global strings are somewhat messy and lint is complaining
// about this. Clean this up.
string kWebserverLastErrMsg; // NOLINT(runtime/string)

string HttpStatusCodeToString(kudu::HttpStatusCode code) {
  switch (code) {
    case kudu::HttpStatusCode::Ok:
      return "200 OK";
    case kudu::HttpStatusCode::TemporaryRedirect:
      return "307 Temporary Redirect";
    case kudu::HttpStatusCode::BadRequest:
      return "400 Bad Request";
    case kudu::HttpStatusCode::AuthenticationRequired:
      return "401 Authentication Required";
    case kudu::HttpStatusCode::NotFound:
      return "404 Not Found";
    case kudu::HttpStatusCode::LengthRequired:
      return "411 Length Required";
    case kudu::HttpStatusCode::RequestEntityTooLarge:
      return "413 Request Entity Too Large";
    case kudu::HttpStatusCode::InternalServerError:
      return "500 Internal Server Error";
    case kudu::HttpStatusCode::ServiceUnavailable:
      return "503 Service Unavailable";
  }
  LOG(FATAL) << "Unexpected HTTP response code";
}

// Return the address of the remote user from the squeasel request info.
Sockaddr GetRemoteAddress(const struct sq_request_info* req) {
  struct sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_port = NetworkByteOrder::FromHost16(req->remote_port);
  addr.sin_addr.s_addr = NetworkByteOrder::FromHost32(req->remote_ip);
  return Sockaddr(addr);
}


// Performs a step of SPNEGO authorization by parsing the HTTP Authorization
// header 'authz_header' and running it through GSSAPI.
//
// If authentication fails or the header is invalid, a bad Status will be
// returned (and the other out-parameters left untouched). Otherwise, the
// out-parameters will be written to, and the function will return either OK or
// Incomplete depending on whether additional SPNEGO steps are required.
Status RunSpnegoStep(const char* authz_header,
                     WebCallbackRegistry::ArgumentMap* resp_headers,
                     string* authn_user) {
  static const char* const kNegotiateHdrName = "WWW-Authenticate";
  static const char* const kNegotiateHdrValue = "Negotiate";
  static const Status kIncomplete = Status::Incomplete("authn incomplete");

  VLOG(2) << "Handling Authorization header "
          << (authz_header ? KUDU_REDACT(authz_header) : "<null>");

  if (!authz_header) {
    EmplaceOrDie(resp_headers, kNegotiateHdrName, kNegotiateHdrValue);
    return kIncomplete;
  }

  string neg_token;
  if (!TryStripPrefixString(authz_header, "Negotiate ", &neg_token)) {
    return Status::InvalidArgument("bad Negotiate header");
  }

  string resp_token_b64;
  bool is_complete;
  RETURN_NOT_OK(gssapi::SpnegoStep(neg_token, &resp_token_b64, &is_complete, authn_user));

  VLOG(2) << "SPNEGO step complete, response token: " << KUDU_REDACT(resp_token_b64);

  if (!resp_token_b64.empty()) {
    EmplaceOrDie(resp_headers, kNegotiateHdrName,
                 Substitute("$0 $1", kNegotiateHdrValue, resp_token_b64));
  }
  return is_complete ? Status::OK() : kIncomplete;
}

}  // anonymous namespace

Webserver::Webserver(const WebserverOptions& opts)
  : opts_(opts),
  context_(nullptr),
  is_started_(false) {
  string host = opts.bind_interface.empty() ? "0.0.0.0" : opts.bind_interface;
  http_address_ = host + ":" + std::to_string(opts.port);
}

Webserver::~Webserver() {
  Stop();
  STLDeleteValues(&path_handlers_);
}

void Webserver::RootHandler(const WebRequest& req,
                            WebResponse* resp) {
  if (is_started_) {
    EasyJson path_handlers = resp->output.Set("path_handlers", EasyJson::kArray);
    for (const PathHandlerMap::value_type& handler : path_handlers_) {
      if (handler.second->is_on_nav_bar()) {
        EasyJson path_handler = path_handlers.PushBack(EasyJson::kObject);
        path_handler["path"] = handler.first;
        path_handler["alias"] = handler.second->alias();
      }
    }
    resp->output["version_info"] = EscapeForHtmlToString(VersionInfo::GetAllVersionInfo());
  } else {
    resp->status_code = HttpStatusCode::TemporaryRedirect;
    resp->response_headers.insert({"Location", "/startup"});
  }
}

void Webserver::BuildArgumentMap(const string& args, ArgumentMap* output) {
  vector<StringPiece> arg_pairs = strings::Split(args, "&");

  for (const StringPiece& arg_pair : arg_pairs) {
    vector<StringPiece> key_value = strings::Split(arg_pair, "=");
    if (key_value.empty()) continue;

    string key;
    if (!UrlDecode(key_value[0].ToString(), &key)) continue;
    string value;
    if (!UrlDecode((key_value.size() >= 2 ? key_value[1].ToString() : ""), &value)) continue;
    boost::to_lower(key);
    (*output)[key] = value;
  }
}

bool Webserver::IsSecure() const {
  return !opts_.certificate_file.empty();
}

Status Webserver::BuildListenSpec(string* spec) const {
  vector<Sockaddr> addrs;
  RETURN_NOT_OK(ParseAddressList(http_address_, 80, &addrs));

  vector<string> parts;
  parts.reserve(addrs.size());
  for (const Sockaddr& addr : addrs) {
    // Mongoose makes sockets with 's' suffixes accept SSL traffic only.
    parts.emplace_back(addr.ToString() + (IsSecure() ? "s" : ""));
  }

  JoinStrings(parts, ",", spec);
  return Status::OK();
}

Status Webserver::Start() {
  vector<string> options;
  if (static_pages_available()) {
    options.emplace_back("document_root");
    options.push_back(opts_.doc_root);
    options.emplace_back("enable_directory_listing");
    options.emplace_back("no");
  }

  if (IsSecure()) {
    // Initialize OpenSSL, and prevent Squeasel from also performing global
    // OpenSSL initialization.
    security::InitializeOpenSSL();
    options.emplace_back("ssl_global_init");
    options.emplace_back("false");

    options.emplace_back("ssl_certificate");
    options.push_back(opts_.certificate_file);

    if (!opts_.private_key_file.empty()) {
      options.emplace_back("ssl_private_key");
      options.push_back(opts_.private_key_file);

      string key_password;
      if (!opts_.private_key_password_cmd.empty()) {
        RETURN_NOT_OK(security::GetPasswordFromShellCommand(opts_.private_key_password_cmd,
                                                            &key_password));
      }
      options.emplace_back("ssl_private_key_password");
      options.push_back(key_password); // May be empty if not configured.
    }

    options.emplace_back("ssl_ciphers");
    options.emplace_back(opts_.tls_ciphers);
    options.emplace_back("ssl_min_version");
    options.emplace_back(opts_.tls_min_protocol);
  }

  if (!opts_.authentication_domain.empty()) {
    options.emplace_back("authentication_domain");
    options.push_back(opts_.authentication_domain);
  }

  if (!opts_.password_file.empty()) {
    if (FIPS_mode()) {
      return Status::IllegalState(
          "Webserver cannot be started with Digest authentication in FIPS approved mode");
    }
    // Mongoose doesn't log anything if it can't stat the password file (but
    // will if it can't open it, which it tries to do during a request).
    if (!Env::Default()->FileExists(opts_.password_file)) {
      ostringstream ss;
      ss << "Webserver: Password file does not exist: " << opts_.password_file;
      return Status::InvalidArgument(ss.str());
    }
    options.emplace_back("global_auth_file");
    options.push_back(opts_.password_file);
  }

  if (opts_.require_spnego) {
    // We assume that security::InitKerberosForServer() has already been called, which
    // ensures that the keytab path has been propagated into this environment variable
    // where the GSSAPI calls will pick it up.
    const char* kt_file = getenv("KRB5_KTNAME");
    if (!kt_file || !Env::Default()->FileExists(kt_file)) {
      return Status::InvalidArgument("Unable to configure web server for SPNEGO authentication: "
                                     "must configure a keytab file for the server");
    }
  }

  options.emplace_back("listening_ports");
  string listening_str;
  RETURN_NOT_OK(BuildListenSpec(&listening_str));
  options.push_back(listening_str);

  // initialize the advertised addresses
  if (!opts_.webserver_advertised_addresses.empty()) {
    RETURN_NOT_OK(ParseAddressList(opts_.webserver_advertised_addresses,
                                   opts_.port,
                                   &webserver_advertised_addresses_));
    for (const Sockaddr& addr : webserver_advertised_addresses_) {
      if (addr.port() == 0) {
        return Status::InvalidArgument("advertising an ephemeral webserver port is not supported",
                                       addr.ToString());
      }
    }
  }

  // Num threads
  options.emplace_back("num_threads");
  options.push_back(std::to_string(opts_.num_worker_threads));

  options.emplace_back("enable_keep_alive");
  options.emplace_back("yes");

  // mongoose ignores SIGCHLD and we need it to run kinit. This means that since
  // mongoose does not reap its own children CGI programs must be avoided.
  // Save the signal handler so we can restore it after mongoose sets it to be ignored.
  sighandler_t sig_chld = signal(SIGCHLD, SIG_DFL);

  sq_callbacks callbacks;
  memset(&callbacks, 0, sizeof(callbacks));
  callbacks.begin_request = &Webserver::BeginRequestCallbackStatic;
  callbacks.log_message = &Webserver::LogMessageCallbackStatic;

  // Options must be a NULL-terminated list of C strings.
  vector<const char*> c_options;
  for (const auto& opt : options) {
    c_options.push_back(opt.c_str());
  }
  c_options.push_back(nullptr);

  // To work around not being able to pass member functions as C callbacks, we store a
  // pointer to this server in the per-server state, and register a static method as the
  // default callback. That method unpacks the pointer to this and calls the real
  // callback.
  context_ = sq_start(&callbacks, reinterpret_cast<void*>(this), &c_options[0]);

  // Restore the child signal handler so wait() works properly.
  signal(SIGCHLD, sig_chld);

  if (context_ == nullptr) {
    Sockaddr addr = Sockaddr::Wildcard();
    addr.set_port(opts_.port);
    TryRunLsof(addr);
    string err_msg = Substitute("Webserver: could not start on address $0", http_address_);
    if (!kWebserverLastErrMsg.empty()) {
      err_msg = Substitute("$0: $1", err_msg, kWebserverLastErrMsg);
    }
    return Status::RuntimeError(err_msg);
  }

  RegisterPathHandler("/", "Home",
                      [this](const WebRequest& req, WebResponse* resp) {
                        this->RootHandler(req, resp);
                      },
                      /*is_styled=*/true, /*is_on_nav_bar=*/true);

  vector<Sockaddr> addrs;
  RETURN_NOT_OK(GetBoundAddresses(&addrs));
  string bound_addresses_str;
  for (const Sockaddr& addr : addrs) {
    if (!bound_addresses_str.empty()) {
      bound_addresses_str += ", ";
    }
    bound_addresses_str += Substitute("$0$1/",
                                      IsSecure() ? "https://" : "http://",
                                      addr.ToString());
  }

  LOG(INFO) << Substitute(
      "Webserver started at $0 using document root $1 and password file $2",
      bound_addresses_str,
      static_pages_available() ? opts_.doc_root : "<none>",
      opts_.password_file.empty() ? "<none>" : opts_.password_file);
  return Status::OK();
}

void Webserver::Stop() {
  if (context_ != nullptr) {
    sq_stop(context_);
    context_ = nullptr;
  }
}

Status Webserver::GetBoundAddresses(std::vector<Sockaddr>* addrs) const {
  if (!context_) {
    return Status::ServiceUnavailable("Not started");
  }

  struct sockaddr_in** sockaddrs;
  int num_addrs;

  if (sq_get_bound_addresses(context_, &sockaddrs, &num_addrs)) {
    return Status::NetworkError("Unable to get bound addresses from Mongoose");
  }

  addrs->reserve(num_addrs);

  for (int i = 0; i < num_addrs; i++) {
    addrs->push_back(Sockaddr(*sockaddrs[i]));
    free(sockaddrs[i]);
  }
  free(sockaddrs);

  return Status::OK();
}

Status Webserver::GetBoundHostPorts(std::vector<HostPort>* hostports) const {
  vector<Sockaddr> addrs;
  RETURN_NOT_OK_PREPEND(GetBoundAddresses(&addrs), "could not get bound webserver addresses");
  return HostPortsFromAddrs(addrs, hostports);
}

Status Webserver::GetAdvertisedAddresses(vector<Sockaddr>* addresses) const {
  if (!context_) {
    return Status::ServiceUnavailable("Not started");
  }
  if (webserver_advertised_addresses_.empty()) {
    return GetBoundAddresses(addresses);
  }
  *addresses = webserver_advertised_addresses_;
  return Status::OK();
}

Status Webserver::GetAdvertisedHostPorts(vector<HostPort>* hostports) const {
  vector<Sockaddr> addrs;
  RETURN_NOT_OK_PREPEND(GetAdvertisedAddresses(&addrs), "could not get bound webserver addresses");
  return HostPortsFromAddrs(addrs, hostports);
}

int Webserver::LogMessageCallbackStatic(const struct sq_connection* /*connection*/,
                                        const char* message) {
  if (message != nullptr) {
    // Using the ERROR severity for squeasel messages: as per source code at
    // https://github.com/cloudera/squeasel/blob/\
    //     c304d3f3481b07bf153979155f02e0aab24d01de/squeasel.c#L392
    // the squeasel server uses the log callback to report on errors.
    {
      static simple_spinlock kErrMsgLock_;
      std::unique_lock<simple_spinlock> l(kErrMsgLock_);
      kWebserverLastErrMsg = message;
    }
    LOG(ERROR) << "Webserver: " << message;
    return 1;
  }
  return 0;
}

sq_callback_result_t Webserver::BeginRequestCallbackStatic(
    struct sq_connection* connection) {
  struct sq_request_info* request_info = sq_get_request_info(connection);
  Webserver* instance = reinterpret_cast<Webserver*>(request_info->user_data);
  return instance->BeginRequestCallback(connection, request_info);
}

sq_callback_result_t Webserver::BeginRequestCallback(
    struct sq_connection* connection,
    struct sq_request_info* request_info) {
  if (strncmp("OPTIONS", request_info->request_method, 7) == 0) {
    // Let Squeasel deal with the request. OPTIONS requests should not require
    // authentication, so do this before doing SPNEGO.
    return SQ_CONTINUE_HANDLING;
  }

  // The last SPNEGO step in a successful authentication may include a response
  // header (e.g. when using mutual authentication).
  PrerenderedWebResponse resp;
  if (opts_.require_spnego) {
    const char* authz_header = sq_get_header(connection, "Authorization");
    string authn_princ;
    Status s = RunSpnegoStep(authz_header, &resp.response_headers, &authn_princ);
    if (s.IsIncomplete()) {
      resp.output << "Must authenticate with SPNEGO.";
      resp.status_code = HttpStatusCode::AuthenticationRequired;
      SendResponse(connection, &resp);
      return SQ_HANDLED_OK;
    }
    if (s.ok() && authn_princ.empty()) {
      s = Status::RuntimeError("SPNEGO indicated complete, but got empty principal");
      // Crash in debug builds, but fall through to treating as an error 500 in
      // release.
      LOG(DFATAL) << "Got no authenticated principal for SPNEGO-authenticated "
                  << " connection from "
                  << GetRemoteAddress(request_info).ToString()
                  << ": " << s.ToString();
    }
    if (!s.ok()) {
      LOG(WARNING) << "Failed to authenticate request from "
                   << GetRemoteAddress(request_info).ToString()
                   << " via SPNEGO: " << s.ToString();
      resp.output << s.ToString();
      resp.status_code = s.IsNotAuthorized() ?
                           HttpStatusCode::AuthenticationRequired :
                           HttpStatusCode::InternalServerError;
      SendResponse(connection, &resp);
      return SQ_HANDLED_OK;
    }

    if (opts_.spnego_post_authn_callback) {
      opts_.spnego_post_authn_callback(authn_princ);
    }

    request_info->remote_user = strdup(authn_princ.c_str());
  }

  PathHandler* handler;
  {
    shared_lock<RWMutex> l(lock_);
    PathHandlerMap::const_iterator it = path_handlers_.find(request_info->uri);
    if (it == path_handlers_.end()) {
      // Let Mongoose deal with this request; returning NULL will fall through
      // to the default handler which will serve files.
      if (!opts_.doc_root.empty() && opts_.enable_doc_root) {
        VLOG(2) << "HTTP File access: " << request_info->uri;
        // TODO(adar): if using SPNEGO, do we need to somehow send the
        // authentication response header here?
        return SQ_CONTINUE_HANDLING;
      }
      resp.output << Substitute("No handler for URI $0\r\n\r\n", request_info->uri);
      resp.status_code = HttpStatusCode::NotFound;
      SendResponse(connection, &resp);
      return SQ_HANDLED_OK;
    }
    handler = it->second;
  }

  return RunPathHandler(*handler, connection, request_info, &resp);
}

sq_callback_result_t Webserver::RunPathHandler(
    const PathHandler& handler,
    struct sq_connection* connection,
    struct sq_request_info* request_info,
    PrerenderedWebResponse* resp) {
  WebRequest req;
  if (request_info->query_string != nullptr) {
    req.query_string = request_info->query_string;
    BuildArgumentMap(request_info->query_string, &req.parsed_args);
  }
  for (int i = 0; i < request_info->num_headers; i++) {
    const auto& h = request_info->http_headers[i];
    string key = h.name;

    // Canonicalize header names to lower case so that we needn't worry about
    // doing case-insensitive comparisons throughout.
    ToLowerCase(&key);
    req.request_headers[key] = h.value;
  }
  req.request_method = request_info->request_method;
  if (req.request_method == "POST") {
    const char* content_len_str = sq_get_header(connection, "Content-Length");
    int32_t content_len = 0;
    if (content_len_str == nullptr ||
        !safe_strto32(content_len_str, &content_len)) {
      resp->status_code = HttpStatusCode::LengthRequired;
      SendResponse(connection, resp);
      return SQ_HANDLED_CLOSE_CONNECTION;
    }
    if (content_len > FLAGS_webserver_max_post_length_bytes) {
      // TODO(wdb): for this and other HTTP requests, we should log the
      // remote IP, etc.
      LOG(WARNING) << "Rejected POST with content length " << content_len;
      resp->status_code = HttpStatusCode::RequestEntityTooLarge;
      SendResponse(connection, resp);
      return SQ_HANDLED_CLOSE_CONNECTION;
    }

    char buf[8192];
    int rem = content_len;
    while (rem > 0) {
      int n = sq_read(connection, buf, std::min<int>(sizeof(buf), rem));
      if (n <= 0) {
        LOG(WARNING) << "error reading POST data: expected "
                     << content_len << " bytes but only read "
                     << req.post_data.size();
        resp->status_code = HttpStatusCode::InternalServerError;
        SendResponse(connection, resp);
        return SQ_HANDLED_CLOSE_CONNECTION;
      }

      req.post_data.append(buf, n);
      rem -= n;
    }
  }

  // Enable or disable redaction from the web UI based on the setting of --redact.
  // This affects operations like default value and scan predicate pretty printing.
  if (kudu::g_should_redact == kudu::RedactContext::ALL) {
    handler.callback()(req, resp);
  } else {
    ScopedDisableRedaction s;
    handler.callback()(req, resp);
  }

  // Should we render with css styles?
  StyleMode use_style = handler.is_styled() && !ContainsKey(req.parsed_args, "raw") ?
                        StyleMode::STYLED : StyleMode::UNSTYLED;
  SendResponse(connection, resp, &req, use_style);
  return SQ_HANDLED_OK;
}

void Webserver::SendResponse(struct sq_connection* connection,
                             PrerenderedWebResponse* resp,
                             const WebRequest* req,
                             StyleMode mode) {
  // If styling was requested, rerender and replace the prerendered output.
  if (mode == StyleMode::STYLED) {
    DCHECK(req);
    stringstream ss;
    RenderMainTemplate(*req, resp->output.str(), &ss);
    resp->output.str(ss.str());
  }

  // Check if gzip compression is accepted by the caller. If so, compress the
  // content and replace the prerendered output.
  const char* accept_encoding_str = sq_get_header(connection, "Accept-Encoding");
  bool is_compressed = false;
  vector<string> encodings = strings::Split(accept_encoding_str, ",");
  for (string& encoding : encodings) {
    StripWhiteSpace(&encoding);
    if (encoding == "gzip") {
      // Don't bother compressing empty content.
      string uncompressed = resp->output.str();
      if (uncompressed.empty()) {
        break;
      }

      ostringstream oss;
      Status s = zlib::CompressLevel(uncompressed, 1, &oss);
      if (s.ok()) {
        resp->output.str(oss.str());
        is_compressed = true;
      } else {
        LOG(WARNING) << "Could not compress output: " << s.ToString();
      }
      break;
    }
  }

  // We've deferred constructing the content for as long as possible; we must
  // do so now so that we can determine the content length.
  string body = resp->output.str();

  // Buffers up the headers and content as follows:
  //
  // <header 1>
  // <header 2>
  // ...
  // <header N>
  // <body>
  ostringstream oss;

  // Write the headers to the buffer first, then write the body.
  oss << Substitute("HTTP/1.1 $0\r\n", HttpStatusCodeToString(resp->status_code));
  oss << Substitute("Content-Type: $0\r\n",
                    mode == StyleMode::STYLED ? "text/html" : "text/plain");
  oss << Substitute("Content-Length: $0\r\n", body.length());
  if (is_compressed) oss << "Content-Encoding: gzip\r\n";
  if (PREDICT_TRUE(FLAGS_webserver_enable_csp)) {
    // TODO(aserbin): add information on when to update the SHA hash and
    //                how to do so (ideally, the exact command line)
    oss << "Content-Security-Policy: default-src 'self';"
        << "style-src 'self' 'unsafe-hashes' 'sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=';"
        << "img-src 'self' data:;\r\n";
  }
  oss << Substitute("X-Frame-Options: $0\r\n", FLAGS_webserver_x_frame_options);
  static const unordered_set<string> kInvalidHeaders = {
    "Content-Length",
    "Content-Type",
    "Content-Security-Policy",
    "X-Frame-Options"
  };
  for (const auto& entry : resp->response_headers) {
    // It's forbidden to override the above headers.
    if (ContainsKey(kInvalidHeaders, entry.first)) {
      LOG(FATAL) << Substitute("Reserved header $0 was overridden by handler",
                               entry.first);
    }
    oss << Substitute("$0: $1\r\n", entry.first, entry.second);
  }
  oss << "\r\n";
  oss << body;

  // Send the buffered response to Squeasel in one go to avoid the latency hit
  // of Nagle's algorithm + delayed TCP acknowledgements.
  //
  // Make sure to use sq_write; sq_printf truncates at 8KB.
  string complete_response = oss.str();
  sq_write(connection, complete_response.c_str(), complete_response.length());
}

void Webserver::AddKnoxVariables(const WebRequest& req, EasyJson* json) {
  if (WebCallbackRegistry::IsProxiedViaKnox(req)) {
    (*json)["base_url"] = "/KNOX-BASE";
  } else {
    (*json)["base_url"] = "";
  }
}

void Webserver::RegisterPathHandler(const string& path, const string& alias,
    const PathHandlerCallback& callback, bool is_styled, bool is_on_nav_bar) {
  string render_path = (path == "/") ? "/home" : path;
  auto wrapped_cb = [=](const WebRequest& req, PrerenderedWebResponse* rendered_resp) {
    WebResponse resp;
    callback(req, &resp);
    AddKnoxVariables(req, &resp.output);
    rendered_resp->status_code = resp.status_code;
    rendered_resp->response_headers = std::move(resp.response_headers);
    // As the home page is redirected to startup until the server's initialization is complete,
    // do not render the page
    if (render_path != "/home" || is_started_) {
      stringstream out;
      Render(render_path, resp.output, is_styled, &out);
      rendered_resp->output << out.rdbuf();
    }
  };
  RegisterPrerenderedPathHandler(path, alias, wrapped_cb, is_styled, is_on_nav_bar);
}

void Webserver::RegisterPrerenderedPathHandler(const string& path, const string& alias,
    const PrerenderedPathHandlerCallback& callback, bool is_styled, bool is_on_nav_bar) {
  std::lock_guard<RWMutex> l(lock_);
  InsertOrDie(&path_handlers_, path, new PathHandler(is_styled, is_on_nav_bar, alias, callback));
}

string Webserver::MustachePartialTag(const string& path) const {
  return Substitute("{{> $0.mustache}}", path);
}

bool Webserver::MustacheTemplateAvailable(const string& path) const {
  if (!static_pages_available()) {
    return false;
  }
  return Env::Default()->FileExists(Substitute("$0$1.mustache", opts_.doc_root, path));
}

static const char* const kMainTemplate = R"(
<!DOCTYPE html>
<html>
  <head>
    <title>Kudu</title>
    <meta charset='utf-8'/>
    <link href='{{base_url}}/bootstrap/css/bootstrap.min.css' rel='stylesheet' media='screen'/>
    <link href='{{base_url}}/bootstrap/css/bootstrap-table.min.css' rel='stylesheet' media='screen'/>
    <script src='{{base_url}}/jquery-3.5.1.min.js' defer></script>
    <script src='{{base_url}}/bootstrap/js/bootstrap.min.js' defer></script>
    <script src='{{base_url}}/bootstrap/js/bootstrap-table.min.js' defer></script>
    <script src='{{base_url}}/kudu.js' defer></script>
    <link href='{{base_url}}/kudu.css' rel='stylesheet'/>
    <link rel='icon' href='{{base_url}}/favicon.ico'>
  </head>
  <body>

    <nav class="navbar navbar-default">
      <div class="container-fluid">
        <div class="navbar-header">
          <a class="navbar-brand" href="{{base_url}}/">
            <img src="{{base_url}}/logo.png" width='61' height='45' alt="Kudu"/>
          </a>
        </div>
        <div id="navbar" class="navbar-collapse collapse">
          <ul class="nav navbar-nav">
           {{#path_handlers}}
            <li><a class="nav-link" href="{{base_url}}{{path}}">{{alias}}</a></li>
           {{/path_handlers}}
          </ul>
        </div><!--/.nav-collapse -->
      </div><!--/.container-fluid -->
    </nav>
    {{^static_pages_available}}
    <div style="color: red">
      <strong>Static pages not available. Configure KUDU_HOME or use the --webserver_doc_root
      flag to fix page styling.</strong>
    </div>
    {{/static_pages_available}}
    {{{content}}}
    </div>
    {{#footer_html}}
    <footer class="footer"><div class="container text-muted">
      {{{.}}}
    </div></footer>
    {{/footer_html}}
  </body>
</html>
)";

void Webserver::RenderMainTemplate(
    const WebRequest& req, const string& content, stringstream* output) {
  EasyJson ej;
  ej["static_pages_available"] = static_pages_available();
  ej["content"] = content;
  AddKnoxVariables(req, &ej);
  std::vector<pair<string, PathHandler*>> paths_and_handlers;

  {
    shared_lock<RWMutex> l(lock_);
    ej["footer_html"] = footer_html_;
    paths_and_handlers.reserve(path_handlers_.size());
    for (const auto& [path, handler] : path_handlers_) {
      paths_and_handlers.emplace_back(path, handler);
    }
  }
  EasyJson path_handlers = ej.Set("path_handlers", EasyJson::kArray);
  for (const auto& [path, handler] : paths_and_handlers) {
    if (handler->is_on_nav_bar()) {
      EasyJson path_handler = path_handlers.PushBack(EasyJson::kObject);
      path_handler["path"] = path;
      path_handler["alias"] = handler->alias();
    }
  }
  RenderTemplate(kMainTemplate, opts_.doc_root, ej.value(), output);
}

void Webserver::Render(const string& path, const EasyJson& ej, bool use_style,
                       stringstream* output) {
  if (MustacheTemplateAvailable(path)) {
    RenderTemplate(MustachePartialTag(path), opts_.doc_root, ej.value(), output);
  } else if (use_style) {
    (*output) << "<pre>" << ej.ToString() << "</pre>";
  } else {
    (*output) << ej.ToString();
  }
}

bool Webserver::static_pages_available() const {
  return !opts_.doc_root.empty() && opts_.enable_doc_root;
}

void Webserver::set_footer_html(const std::string& html) {
  std::lock_guard<RWMutex> l(lock_);
  footer_html_ = html;
}

void Webserver::SetStartupComplete(bool state) {
  is_started_ = state;
}

} // namespace kudu
