Custom Schemes
Saucer has support for adding user-defined custom schemes. This mechanism is used by embedding under the hood.
Register Scheme
To add a new custom scheme, you must register the scheme-name before creating any saucer instances.
#include <saucer/smartview.hpp>
int main()
{
saucer::webview::register_scheme("demo");
auto app = saucer::application::acquire({
.id = "scheme-demo",
});
saucer::smartview smartview{{
.application = app,
}};
smartview.show();
app->run();
return 0;
}
Handle Scheme
After registering a scheme it can be handled per-instance. To do so, call webview.handle_scheme("name", <callback>)
.
The callback will receive a const saucer::scheme::request &
and should return either a saucer::scheme::response
or an error.
The given request data contains various information on the requested resource, such as the url, request method, body and headers.
#include <saucer/smartview.hpp>
#include <print>
int main()
{
saucer::webview::register_scheme("demo");
auto app = saucer::application::acquire({
.id = "scheme-demo",
});
saucer::smartview smartview{{
.application = app,
}};
smartview.handle_scheme("demo",
[](const saucer::scheme::request &req) -> saucer::scheme::handler::result_type
{
std::println("Requested: \"{}\" ({})", req.url(), req.method());
return saucer::scheme::response{
.data = saucer::make_stash("<html><body>Hello from scheme handler!</body></html>"),
.mime = "text/html",
};
});
smartview.set_url("demo://data/index.html");
smartview.show();
app->run();
return 0;
}
Due to upstream issues related to the JS-Fetch API on WebView2, it is required to specify an authority for all scheme-urls.
If none is specified, the given file will be treated as the authority, which may lead to unexpected results.
smartview.set_url("demo://index.html");
smartview.set_url("demo://root/index.html"); // "root" can be any text
It is recommended to always add an authority to your custom-scheme url due to this issue.
As you can see, the response consists of some data
and the mime
-type. Headers and the status-code can also be optionally specified.
Stash
You might've noticed that saucer::make_stash
was used in the example above.
A stash is a storage type for raw-bytes that can be either owning or non-owning.
saucer::stash<>::from(/*data*/);
saucer::stash<>::view(/*data*/);
You can use saucer::make_stash
to conditionally create a (non-)owning stash depending on the given data-type.
Be careful when using stash<>::view
. The returned stash will only reference the given data - only use it when you know that the data will outlive the stash.
It is also possible to create a lazy
stash, which will compute the data on the first time it is requested and then re-use it later. For more information see embedding.