xo-expression2/xo-websock/include/xo/websock/DynamicEndpoint.hpp
Roland Conybeare dd1a6b1afc Add 'xo-websock/' from commit '57bf06a68f'
git-subtree-dir: xo-websock
git-subtree-mainline: 97eefaea22
git-subtree-split: 57bf06a68f
2025-05-11 15:08:51 -05:00

126 lines
4.8 KiB
C++

/* file DynamicEndpoint.hpp
*
* author: Roland Conybeare, Sep 2022
*/
#pragma once
#include "EndpointUtil.hpp"
#include "xo/webutil/HttpEndpointDescr.hpp"
#include "xo/webutil/StreamEndpointDescr.hpp"
#include "xo/webutil/Alist.hpp"
#include <regex>
namespace xo {
namespace web {
/* a dynamic http endpoint. content served on-browser-demand
* by user-provided callback
*/
class DynamicEndpoint {
public:
using AbstractSink = xo::reactor::AbstractSink;
using CallbackId = fn::CallbackId;
public:
static std::unique_ptr<DynamicEndpoint> make_http(std::string uri_pattern,
HttpEndpointFn http_cb) {
return (std::unique_ptr<DynamicEndpoint>
(new DynamicEndpoint(std::move(uri_pattern),
std::move(http_cb),
nullptr,
nullptr)));
} /*make_http*/
static std::unique_ptr<DynamicEndpoint> make_stream(std::string uri_pattern,
StreamSubscribeFn sub_fn,
StreamUnsubscribeFn unsub_fn) {
return (std::unique_ptr<DynamicEndpoint>
(new DynamicEndpoint(std::move(uri_pattern),
nullptr,
std::move(sub_fn),
std::move(unsub_fn))));
} /*make_stream*/
std::string stem() const {
return EndpointUtil::stem(this->uri_pattern_);
} /*stem*/
#ifdef NOT_USING
/* true iff incoming_uri matches .uri_pattern */
bool is_match(std::string const & incoming_uri) const {
/* c++ regex = javascript regexes,
* so these characters are special:
* ^ $ \ . * + ? ( ) [ ] { } |
*/
} /*is_match*/
#endif
/* get html from this endpoint, on behalf of uri=incoming_uri;
* write html on *p_os
*
* require: non-null http_fn
*/
void http_response(std::string const & incoming_uri,
std::ostream * p_os) const;
/* subscribe stream from this endpoint, on behalf of uri=incoming_uri.
* send output to ws_sink
*/
CallbackId subscribe(std::string const & incoming_uri,
rp<AbstractSink> const & ws_sink) const;
/* unsubscribe stream from this endpoint;
* reverses the effect of a previous call to .subscribe()
* that returned id
*/
void unsubscribe(CallbackId id) const;
private:
explicit DynamicEndpoint(std::string uri_pattern,
HttpEndpointFn http_fn,
StreamSubscribeFn subscribe_fn,
StreamUnsubscribeFn unsubscribe_fn);
private:
/* pattern for this endpoint
* can be string like
* /fixed/stem/${a}/more/fixed/stuff/${b}
* in which case:
*
* 1. will match uris like:
* /fixed/stem/apple/more/fixed/stuff/bananas
* --> invoke callback with Alist
* ("a" -> "apple", "b" -> "bananas")
* endpoint will be stored in WebserverImpl.stem_map
* under fixed prefix, in this case
* /fixed/stem/
*
* 2. will not match uris like:
* /fixed/stem/app/le/more/fixed/stuff/bononos
*/
std::string uri_pattern_;
/* regex for matching input that satisfies .uri_pattern:
* each occurrence of
* ${...} replaced by [[:alnum:]]+
*/
std::regex uri_regex_;
/* variables found in .uri_pattern,
* in the order in which they appear
* if .uri_pattern is
* /fixed/stem/${a}/more/fixed/stuff/${b}
* then .var_v will be:
* ["a", "b"]
*/
std::vector<std::string> var_v_;
/* run this function to produce an http response */
HttpEndpointFn http_fn_;
/* run this function to subscribe event stream */
StreamSubscribeFn subscribe_fn_;
/* run this function to unsubscribe event stream */
StreamUnsubscribeFn unsubscribe_fn_;
}; /*DynamicEndpoint*/
} /*namespace web*/
} /*namespace xo*/
/* end DynamicEndpoint.hpp */