5 #include "util/uring/http_handler.h" 7 #include <boost/beast/core.hpp> 8 #include <boost/beast/http.hpp> 10 #include "base/logging.h" 15 using namespace boost;
16 namespace h2 = beast::http;
22 void FilezHandler(
const QueryArgs& args, HttpContext* send) {
23 StringPiece file_name;
24 for (
const auto& k_v : args) {
25 if (k_v.first ==
"file") {
26 file_name = k_v.second;
29 if (file_name.empty()) {
30 http::StringResponse resp = MakeStringResponse(h2::status::unauthorized);
31 return send->Invoke(std::move(resp));
35 string fname = strings::AsString(file_name);
36 auto ec = LoadFileResponse(fname, &fresp);
38 StringResponse res = MakeStringResponse(h2::status::not_found);
39 SetMime(kTextMime, &res);
40 if (ec == boost::system::errc::no_such_file_or_directory)
41 res.body() =
"The resource '" + fname +
"' was not found.";
43 res.body() =
"Error '" + ec.message() +
"'.";
44 return send->Invoke(std::move(res));
47 return send->Invoke(std::move(fresp));
52 HttpListenerBase::HttpListenerBase() {
54 "https://rawcdn.githack.com/romange/gaia/master/util/http/" 56 resource_prefix_ =
"https://cdn.jsdelivr.net/gh/romange/gaia/util/http";
59 bool HttpListenerBase::HandleRoot(
const RequestType& request,
60 HttpContext* cntx)
const {
61 StringPiece target = as_absl(request.target());
62 if (target ==
"/favicon.ico") {
63 h2::response<h2::string_body> resp =
64 MakeStringResponse(h2::status::moved_permanently);
65 resp.set(h2::field::location, favicon_);
66 resp.set(h2::field::server,
"GAIA");
67 resp.keep_alive(request.keep_alive());
69 cntx->Invoke(std::move(resp));
73 StringPiece path, query;
74 tie(path, query) = ParseQuery(target);
75 auto args = SplitQuery(query);
78 cntx->Invoke(BuildStatusPage(args, resource_prefix_));
82 if (path ==
"/flagz") {
83 h2::response<h2::string_body> resp(h2::status::ok, request.version());
84 cntx->Invoke(ParseFlagz(args));
88 if (path ==
"/filez") {
89 FilezHandler(args, cntx);
93 if (path ==
"/profilez") {
94 cntx->Invoke(ProfilezHandler(args));
100 bool HttpListenerBase::RegisterCb(StringPiece path, RequestCb cb) {
101 CbInfo cb_info{.cb = cb};
103 auto res = cb_map_.emplace(path, cb_info);
107 HttpHandler2::HttpHandler2(
const HttpListenerBase* base) : base_(base) {
110 void HttpHandler2::HandleRequests() {
112 beast::flat_buffer buffer;
115 system::error_code ec;
116 AsioStreamAdapter<> asa(socket_);
119 h2::read(asa, buffer, request, ec);
123 HttpContext cntx(asa);
124 VLOG(1) <<
"Full Url: " << request.target();
125 HandleOne(request, &cntx);
127 VLOG(1) <<
"HttpHandler2 exit";
130 void HttpHandler2::HandleOne(
const RequestType& req, HttpContext* cntx) {
133 if (base_->HandleRoot(req, cntx)) {
136 StringPiece target = as_absl(req.target());
137 StringPiece path, query;
138 tie(path, query) = ParseQuery(target);
139 VLOG(2) <<
"Searching for " << path;
141 auto it = base_->cb_map_.find(path);
142 if (it == base_->cb_map_.end()) {
143 h2::response<h2::string_body> resp(h2::status::unauthorized, req.version());
144 return cntx->Invoke(std::move(resp));
146 auto args = SplitQuery(query);
147 it->second.cb(args, cntx);
bool IsOpen() const
IsOpen does not promise that the socket is TCP connected or live,.