Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
lint:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

- name: Install dependencies
run: sudo apt install -y clang-format
Expand All @@ -25,15 +25,15 @@ jobs:
container: archlinux:latest
steps:
- name: Install dependencies
run: pacman -Syu --noconfirm base-devel clang cmake ninja extra-cmake-modules fmt libuv boost lsof
run: pacman -Syu --noconfirm base-devel clang cmake ninja extra-cmake-modules libuv boost lsof

- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
repository: fcitx/fcitx5
path: fcitx5

- name: Cache fcitx5 data files
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: 'fcitx5/**/*.tar.*'
key: ${{ runner.os }}-${{ hashFiles('fcitx5/src/modules/spell/CMakeLists.txt')}}
Expand All @@ -46,7 +46,7 @@ jobs:
-DENABLE_KEYBOARD=Off -DENABLE_X11=Off -DENABLE_WAYLAND=Off -DENABLE_ENCHANT=Off
-DENABLE_DBUS=Off -DENABLE_SERVER=Off -DENABLE_EMOJI=Off -DUSE_SYSTEMD=Off -DENABLE_TEST=OFF

- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
path: fcitx5-beast

Expand Down
17 changes: 16 additions & 1 deletion src/beast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#include <unistd.h>
#endif

#define REMOTE_PREFIX "/remote/"

namespace beast = boost::beast;
namespace http = beast::http;
namespace net = boost::asio;
Expand All @@ -19,6 +21,10 @@ namespace fcitx {

ConfigSetter configSetter_ = [](const char *, const char *) {};
ConfigGetter configGetter_ = [](const char *) { return ""; };
RemoteHandler remoteHandler_ =
[](const std::string_view, const char *) -> std::pair<bool, std::string> {
return {false, ""};
};

Beast::Beast(Instance *instance) : instance_(instance) { reloadConfig(); }

Expand Down Expand Up @@ -109,7 +115,7 @@ class http_connection

// Construct a response message based on the program state.
void create_response() {
if (stringutils::startsWith(request_.target(), "/config/")) {
if (request_.target().starts_with("/config/")) {
std::string uri = "fcitx:/";
uri += request_.target();
if (request_.method() == http::verb::get) {
Expand All @@ -122,6 +128,15 @@ class http_connection
beast::ostream(response_.body()) << "";
configSetter_(uri.c_str(), request_.body().data());
}
} else if (request_.target().starts_with(REMOTE_PREFIX) &&
request_.method() == http::verb::post) {
std::string_view command = request_.target();
stringutils::consumePrefix(command, REMOTE_PREFIX);
auto res = remoteHandler_(command, request_.body().data());
response_.set(http::field::content_type, "text/plain");
response_.result(res.first ? http::status::ok
: http::status::bad_request);
beast::ostream(response_.body()) << res.second;
} else {
response_.result(http::status::not_found);
response_.set(http::field::content_type, "text/plain");
Expand Down
4 changes: 4 additions & 0 deletions src/beast.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ namespace asio = boost::asio;

using ConfigGetter = std::function<std::string(const char *)>;
using ConfigSetter = std::function<void(const char *, const char *)>;
using RemoteHandler = std::function<std::pair<bool, std::string>(
const std::string_view, const char *)>;

namespace fcitx {

Expand Down Expand Up @@ -58,6 +60,7 @@ FCITX_CONFIGURATION(BeastConfig,

extern ConfigGetter configGetter_;
extern ConfigSetter configSetter_;
extern RemoteHandler remoteHandler_;

class Beast : public AddonInstance {
public:
Expand All @@ -72,6 +75,7 @@ class Beast : public AddonInstance {
void reloadConfig() override;
void setConfigGetter(ConfigGetter getter) { configGetter_ = getter; }
void setConfigSetter(ConfigSetter setter) { configSetter_ = setter; }
void setRemoteHandler(RemoteHandler handler) { remoteHandler_ = handler; }

private:
static const inline std::string ConfPath = "conf/beast.conf";
Expand Down
21 changes: 20 additions & 1 deletion test/testbeast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ int main() {

bool getterCalled = false;
bool setterCalled = false;
bool remoteCalled = false;

beast->setConfigGetter([&](const char *) {
getterCalled = true;
Expand All @@ -37,6 +38,11 @@ int main() {
setterCalled = true;
return "";
});
beast->setRemoteHandler([&](const std::string_view,
const char *) -> std::pair<bool, std::string> {
remoteCalled = true;
return {true, ""};
});

// Listen on default unix socket.
assert(std::system("lsof /tmp/fcitx5.sock") == 0);
Expand All @@ -53,6 +59,12 @@ int main() {
"http://fcitx/config/addon/beast") == 0);
assert(setterCalled);

// Remote works.
assert(!remoteCalled);
assert(std::system("curl --unix-socket /tmp/fcitx5.sock -X POST "
"http://fcitx/remote/c") == 0);
assert(remoteCalled);

// Unix socket path reset works.
auto config = dynamic_cast<const BeastConfig *>(beast->getConfig());
RawConfig raw;
Expand All @@ -73,19 +85,26 @@ int main() {

getterCalled = false;
setterCalled = false;
remoteCalled = false;

// Getter works over TCP.
assert(!getterCalled);
assert(std::system("curl "
"http://127.0.0.1:32489/config/addon/beast") == 0);
assert(getterCalled);

// Setter works ovet TCP.
// Setter works over TCP.
assert(!setterCalled);
assert(std::system("curl -X POST -d '{}' "
"http://127.0.0.1:32489/config/addon/beast") == 0);
assert(setterCalled);

// Remote works over TCP.
assert(!remoteCalled);
assert(std::system("curl -X POST "
"http://127.0.0.1:32489/remote/c") == 0);
assert(remoteCalled);

// Tcp port reset works.
cfg.tcp.mutableValue()->port.setValue(32490);
cfg.save(raw);
Expand Down