http_common.cc
1 // Copyright 2020, Beeri 15. All rights reserved.
2 // Author: Roman Gershman (romange@gmail.com)
3 //
4 
5 #include "util/http/http_common.h"
6 
7 #include "absl/strings/match.h"
8 #include "absl/strings/numbers.h"
9 #include "absl/strings/str_split.h"
10 #include "base/flags.h"
11 #include "base/logging.h"
12 #include "strings/stringpiece.h"
13 
14 namespace util {
15 namespace http {
16 using namespace std;
17 using namespace boost;
18 
19 namespace h2 = beast::http;
20 
21 namespace {
22 
23 void HandleVModule(StringPiece str) {
24  vector<StringPiece> parts = absl::StrSplit(str, ",", absl::SkipEmpty());
25  for (StringPiece p : parts) {
26  size_t sep = p.find('=');
27  int32_t level = 0;
28  if (sep != StringPiece::npos &&
29  absl::SimpleAtoi(p.substr(sep + 1), &level)) {
30  string module_expr = strings::AsString(p.substr(0, sep));
31  int prev = google::SetVLOGLevel(module_expr.c_str(), level);
32  LOG(INFO) << "Setting module " << module_expr << " to loglevel " << level
33  << ", prev: " << prev;
34  }
35  }
36 }
37 
38 } // namespace
39 
40 const char kHtmlMime[] = "text/html";
41 const char kJsonMime[] = "application/json";
42 const char kSvgMime[] = "image/svg+xml";
43 const char kTextMime[] = "text/plain";
44 const char kXmlMime[] = "application/xml";
45 const char kBinMime[] = "application/octet-stream";;
46 
47 QueryParam ParseQuery(StringPiece str) {
48  std::pair<StringPiece, StringPiece> res;
49  size_t pos = str.find('?');
50  res.first = str.substr(0, pos);
51  if (pos != StringPiece::npos) {
52  res.second = str.substr(pos + 1);
53  }
54  return res;
55 }
56 
57 QueryArgs SplitQuery(StringPiece query) {
58  vector<StringPiece> args = absl::StrSplit(query, '&');
59  vector<std::pair<StringPiece, StringPiece>> res(args.size());
60  for (size_t i = 0; i < args.size(); ++i) {
61  size_t pos = args[i].find('=');
62  res[i].first = args[i].substr(0, pos);
63  res[i].second =
64  (pos == StringPiece::npos) ? StringPiece() : args[i].substr(pos + 1);
65  }
66  return res;
67 }
68 
69 h2::response<h2::string_body> ParseFlagz(const QueryArgs& args) {
70  h2::response<h2::string_body> response(h2::status::ok, 11);
71 
72  StringPiece flag_name;
73  StringPiece value;
74  for (const auto& k_v : args) {
75  if (k_v.first == "flag") {
76  flag_name = k_v.second;
77  } else if (k_v.first == "value") {
78  value = k_v.second;
79  }
80  }
81  if (!flag_name.empty()) {
82  google::CommandLineFlagInfo flag_info;
83  string fname = strings::AsString(flag_name);
84  if (!google::GetCommandLineFlagInfo(fname.c_str(), &flag_info)) {
85  response.body() = "Flag not found \n";
86  } else {
87  SetMime(kHtmlMime, &response);
88  response.body()
89  .append("<p>Current value ")
90  .append(flag_info.current_value)
91  .append("</p>");
92  string new_val = strings::AsString(value);
93  string res = google::SetCommandLineOption(fname.c_str(), new_val.c_str());
94  response.body().append("Flag ").append(res);
95 
96  if (flag_name == "vmodule") {
97  HandleVModule(value);
98  }
99  }
100  } else if (args.size() == 1) {
101  LOG(INFO) << "Printing all flags";
102  std::vector<google::CommandLineFlagInfo> flags;
103  google::GetAllFlags(&flags);
104  for (const auto& v : flags) {
105  response.body()
106  .append("--")
107  .append(v.name)
108  .append(": ")
109  .append(v.current_value)
110  .append("\n");
111  SetMime(kTextMime, &response);
112  }
113  }
114  return response;
115 }
116 
117 ::boost::system::error_code LoadFileResponse(absl::string_view fname,
118  FileResponse* resp) {
119  FileResponse::body_type::value_type body;
120  system::error_code ec;
121  body.open(fname.data(), boost::beast::file_mode::scan, ec);
122  if (ec) {
123  return ec;
124  }
125 
126  size_t sz = body.size();
127  *resp =
128  FileResponse{std::piecewise_construct, std::make_tuple(std::move(body)),
129  std::make_tuple(h2::status::ok, 11)};
130 
131  const char* mime = kHtmlMime;
132  if (absl::EndsWith(fname, ".svg")) {
133  mime = kSvgMime;
134  } else if (absl::EndsWith(fname, ".html")) {
135  mime = kHtmlMime;
136  } else {
137  mime = kTextMime;
138  }
139  SetMime(mime, resp);
140  resp->content_length(sz);
141  resp->swap(*resp);
142 
143  return ec;
144 }
145 
146 } // namespace http
147 } // namespace util