ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
HttpServerRequestHandler.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 // ----------------------------------------------------------------------------
8 // Contains source code from
9 // https://github.com/mpromonet/webrtc-streamer
10 //
11 // This software is in the public domain, furnished "as is", without technical
12 // support, and with no warranty, express or implied, as to its usefulness for
13 // any purpose.
14 // ----------------------------------------------------------------------------
15 
17 
18 #include <Logging.h>
19 
20 #include <functional>
21 
22 namespace cloudViewer {
23 namespace visualization {
24 namespace webrtc_server {
25 
26 static int LogMessage(const struct mg_connection *conn, const char *message) {
27  utility::LogInfo("CivetServer: {}", message);
28  return 0;
29 }
30 
31 static struct CivetCallbacks _callbacks;
32 static const struct CivetCallbacks *getCivetCallbacks() {
33  memset(static_cast<void *>(&_callbacks), 0, sizeof(_callbacks));
34  _callbacks.log_message = &LogMessage;
35  return &_callbacks;
36 }
37 
38 class RequestHandler : public CivetHandler {
39 public:
41  : func_(func) {}
42 
43  bool handle(CivetServer *server, struct mg_connection *conn) {
44  bool ret = false;
45  const struct mg_request_info *req_info = mg_get_request_info(conn);
46 
47  // Read input.
48  Json::Value in = this->getInputMessage(req_info, conn);
49 
50  // Invoke API implementation.
51  Json::Value out(func_(req_info, in));
52 
53  // Fill out.
54  std::string answer = "";
55  if (out.isNull() == false) {
56  answer = Json::writeString(writer_builder_, out);
57  mg_printf(conn, "HTTP/1.1 200 OK\r\n");
58  mg_printf(conn, "Access-Control-Allow-Origin: *\r\n");
59  mg_printf(conn, "Content-Type: text/plain\r\n");
60  mg_printf(conn, "Content-Length: %zd\r\n", answer.size());
61  mg_printf(conn, "\r\n");
62  mg_write(conn, answer.c_str(), answer.size());
63  ret = true;
64  }
65 
67  "request_uri: {}, local_uri: {}, request_method: {}, "
68  "query_string: {}, content_length: {}, answer: {}.",
69  req_info->request_uri, req_info->local_uri,
70  req_info->request_method,
71  req_info->query_string ? req_info->query_string : "nullptr",
72  req_info->content_length, answer);
73  return ret;
74  }
75  bool handleGet(CivetServer *server, struct mg_connection *conn) override {
76  return handle(server, conn);
77  }
78  bool handlePost(CivetServer *server, struct mg_connection *conn) override {
79  return handle(server, conn);
80  }
81 
82 private:
84  Json::StreamWriterBuilder writer_builder_;
85  Json::CharReaderBuilder reader_builder_;
86 
87  Json::Value getInputMessage(const struct mg_request_info *req_info,
88  struct mg_connection *conn) {
89  Json::Value json_message;
90 
91  // Read input.
92  long long tlen = req_info->content_length;
93  if (tlen > 0) {
94  std::string body;
95  long long nlen = 0;
96  const long long bufSize = 1024;
97  char buf[bufSize];
98  while (nlen < tlen) {
99  long long rlen = tlen - nlen;
100  if (rlen > bufSize) {
101  rlen = bufSize;
102  }
103  rlen = mg_read(conn, buf, (size_t)rlen);
104  if (rlen <= 0) {
105  break;
106  }
107  body.append(buf, rlen);
108 
109  nlen += rlen;
110  }
111 
112  // Parse in.
113  std::unique_ptr<Json::CharReader> reader(
114  reader_builder_.newCharReader());
115  std::string errors;
116  if (!reader->parse(body.c_str(), body.c_str() + body.size(),
117  &json_message, &errors)) {
118  utility::LogWarning("Received unknown message: {}, errors: {}.",
119  body, errors);
120  }
121  }
122  return json_message;
123  }
124 };
125 
127  std::map<std::string, HttpFunction> &func,
128  const std::vector<std::string> &options)
129  : CivetServer(options, getCivetCallbacks()) {
130  // Register handlers.
131  for (auto it : func) {
132  this->addHandler(it.first, new RequestHandler(it.second));
133  }
134 }
135 
136 } // namespace webrtc_server
137 } // namespace visualization
138 } // namespace cloudViewer
HttpServerRequestHandler(std::map< std::string, HttpFunction > &func, const std::vector< std::string > &options)
std::function< Json::Value(const struct mg_request_info *req_info, const Json::Value &)> HttpFunction
RequestHandler(HttpServerRequestHandler::HttpFunction &func)
bool handle(CivetServer *server, struct mg_connection *conn)
bool handlePost(CivetServer *server, struct mg_connection *conn) override
bool handleGet(CivetServer *server, struct mg_connection *conn) override
#define LogWarning(...)
Definition: Logging.h:72
#define LogInfo(...)
Definition: Logging.h:81
#define LogDebug(...)
Definition: Logging.h:90
static int LogMessage(const struct mg_connection *conn, const char *message)
static const struct CivetCallbacks * getCivetCallbacks()
Generic file read and write utility for python interface.