3#include <uwebsockets/App.h>
5#include <BS_thread_pool.hpp>
11#include <nlohmann/json.hpp>
66 std::string queryString, std::vector<std::pair<std::string, std::string>> headers,
68 : url_(std::move(
url)),
70 queryString_(std::move(queryString)),
71 headers_(std::move(headers)),
72 body_(std::move(
body)) {}
75 std::string_view
url()
const {
return url_; }
79 const std::string&
body()
const {
return body_; }
86 for (
const auto& [key, value] : headers_) {
96 bool accepts(std::string_view contentType)
const {
97 return header(
"accept").find(contentType) != std::string_view::npos;
108 for (
const auto& [key, value] : parameters_) {
131 std::optional<std::string>
query(std::string_view key)
const;
138 template <
typename T>
144 template <
typename T>
145 std::optional<T>
queryAs(std::string_view key)
const {
146 auto value =
query(key);
147 return value ? parseNumber<T>(*value) : std::nullopt;
151 template <
typename T>
152 static std::optional<T> parseNumber(std::string_view
text) {
156 const bool hex =
text.size() > 2 &&
text[0] ==
'0' && (
text[1] ==
'x' ||
text[1] ==
'X');
157 const std::string_view digits = hex ?
text.substr(2) :
text;
159 const auto [ptr, ec] =
160 std::from_chars(digits.data(), digits.data() + digits.size(), value, hex ? 16 : 10);
161 if (ec != std::errc{} || ptr != digits.data() + digits.size()) {
168 std::vector<std::pair<std::string, std::string>> parameters_;
169 std::string queryString_;
170 std::vector<std::pair<std::string, std::string>> headers_;
184 std::vector<std::pair<std::string, std::string>>
headers;
257template <
typename Op>
258Response timed(Op&& op, std::string errorStatus =
"500 Internal Server Error") {
259 const auto t0 = std::chrono::steady_clock::now();
260 auto result = std::forward<Op>(op)();
262 std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - t0);
274template <
typename Op,
typename StatusOf>
275 requires std::invocable<StatusOf&, const typename std::invoke_result_t<Op&>::error_type&>
277 const auto t0 = std::chrono::steady_clock::now();
278 auto result = std::forward<Op>(op)();
280 std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - t0);
282 return withWireTime(
error(std::string(statusOf(result.error())), result.error().message),
303 Router(uWS::SSLApp& app, uWS::Loop* loop, BS::light_thread_pool& pool,
304 const std::atomic<bool>& stopping, std::string_view corsOrigin)
305 : app_(app), loop_(loop), pool_(pool), stopping_(stopping), corsOrigin_(corsOrigin) {}
309 add(
"GET", pattern, std::move(handler),
false);
313 add(
"POST", pattern, std::move(handler),
true);
317 add(
"PUT", pattern, std::move(handler),
true);
321 add(
"DELETE", pattern, std::move(handler),
false);
325 void add(std::string_view method,
const std::string& pattern,
Handler handler,
bool hasBody);
329 BS::light_thread_pool& pool_;
341 const std::atomic<bool>& stopping_;
342 std::string_view corsOrigin_;
A request, snapshotted on the loop thread so a handler can outlive it.
Definition router.h:63
std::string_view url() const
The full request path.
Definition router.h:75
const std::string & body() const
The request body, empty for methods that carry none. Complete — a handler never sees a partial body,...
Definition router.h:79
std::optional< T > queryAs(std::string_view key) const
A query value parsed as an integer, or std::nullopt if absent or not one.
Definition router.h:145
std::optional< T > parameterAs(std::string_view name) const
A path parameter parsed as an integer, or std::nullopt if it is absent or not one.
Definition router.h:139
std::string_view parameter(std::string_view name) const
A path parameter by the name the route pattern declared (:slavePosition), or empty.
Definition router.h:107
Request(std::string url, std::vector< std::pair< std::string, std::string > > parameters, std::string queryString, std::vector< std::pair< std::string, std::string > > headers, std::string body)
Definition router.h:65
std::string_view header(std::string_view name) const
A request header by name, lower-cased as uWS delivers it, or empty when absent.
Definition router.h:85
bool accepts(std::string_view contentType) const
Whether Accept asks for contentType. Substring, matching how these endpoints have always negotiated: ...
Definition router.h:96
std::optional< std::string > query(std::string_view key) const
A query-string value by key, percent-decoded, or std::nullopt when it has no value.
Definition router.cc:102
Registers routes whose handlers run off the event loop.
Definition router.h:295
void put(const std::string &pattern, Handler handler)
Registers handler for PUT pattern; the body is accumulated before dispatch.
Definition router.h:316
void post(const std::string &pattern, Handler handler)
Registers handler for POST pattern; the body is accumulated before dispatch.
Definition router.h:312
void del(const std::string &pattern, Handler handler)
Registers handler for DELETE pattern.
Definition router.h:320
void get(const std::string &pattern, Handler handler)
Registers handler for GET pattern. Path parameters are :name as in uWS.
Definition router.h:308
Router(uWS::SSLApp &app, uWS::Loop *loop, BS::light_thread_pool &pool, const std::atomic< bool > &stopping, std::string_view corsOrigin)
Definition router.h:303
mailboxStatusFmmu useCompleteAccess parameters
Definition config.h:245
std::string name
Catalogue name, e.g. "sm2".
Definition eni_request.cc:37
HTTP-transport glue shared by the built-in server and route plug-in libs.
Definition router.cc:14
Response badRequest(std::string_view message)
A 400 with message — the most common failure, so it gets a name.
Definition router.cc:161
std::vector< std::string > parameterNames(std::string_view pattern)
The :name tokens of a route pattern, in the order uWS will index them.
Definition router.cc:176
std::string percentDecode(std::string_view text)
Percent-decodes a URL path component — %20 to a space, %2F to a slash.
Definition router.cc:119
Response timed(Op &&op, std::string errorStatus="500 Internal Server Error")
Runs a device operation, times it, and turns its std::expected into a timed response.
Definition router.h:258
std::function< Response(const Request &)> Handler
What a route does: a pure function from a snapshotted request to a response.
Definition router.h:289
Response statusOnly(std::string status)
A bare status response with no body — a 202 that means "under way", a 204 delete.
Definition router.cc:165
Response json(const nlohmann::json &body)
A 200 response carrying body as JSON.
Definition router.cc:140
Response withWireTime(Response response, std::chrono::microseconds wireUs)
Attaches the server-measured device time (X-Wire-Us) to response and returns it.
Definition router.cc:170
Response notFound(std::string_view message)
A 404 with message.
Definition router.cc:163
std::string text
Definition soem_fieldbus_driver.cc:1254
FoeError error
Definition soem_fieldbus_driver.cc:1307
std::size_t bytes
Definition spoe_connection.cc:24
A complete response, produced off the loop and written by the framework.
Definition router.h:178
std::vector< std::pair< std::string, std::string > > headers
Definition router.h:184
std::string body
Definition router.h:181
std::string contentType
Definition router.h:180
std::string status
Definition router.h:179