Skip to content

Commit

Permalink
Use binary http channel for podman socket
Browse files Browse the repository at this point in the history
Cockpit's (default) text channels ignore frames with split UTF-8
multi-byte characters. This causes broken JSON. This is ultimately an
issue with cockpit's channel API design, and Cockpit should hide that by
buffering and partially decoding text channel frames, see
cockpit-project/cockpit#19235

Until that happens, convert the REST API to use a binary channel.

Fixes #1733
  • Loading branch information
martinpitt committed Jun 5, 2024
1 parent fecb8a2 commit 346d0c3
Showing 1 changed file with 26 additions and 13 deletions.
39 changes: 26 additions & 13 deletions src/rest.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,39 @@ function manage_error(reject, error, content) {
// calls are async, so keep track of a call counter to associate a result with a call
let call_id = 0;

const NL = '\n'.charCodeAt(0); // always 10, but avoid magic constant

function connect(address, system) {
/* This doesn't create a channel until a request */
const http = cockpit.http(address, { superuser: system ? "require" : null });
/* HACK: use binary channel to work around https://github.com/cockpit-project/cockpit/issues/19235 */
const http = cockpit.http(address, { superuser: system ? "require" : null, binary: true });
const connection = {};
const decoder = new TextDecoder();

connection.monitor = function(options, callback, system, return_raw) {
return new Promise((resolve, reject) => {
let buffer = "";
let buffer = new Uint8Array();

http.request(options)
.stream(data => {
if (return_raw)
callback(data);
else {
buffer += data;
const chunks = buffer.split("\n");
buffer = chunks.pop();
buffer = new Uint8Array([...buffer, ...data]);

// split the buffer into lines on NL (this is safe with UTF-8)
for (;;) {
const idx = buffer.indexOf(NL);
if (idx < 0)
break;

chunks.forEach(chunk => {
debug(system, "monitor", chunk);
callback(JSON.parse(chunk));
});
const line = buffer.slice(0, idx);
buffer = buffer.slice(idx + 1);

const line_str = decoder.decode(line);
debug(system, "monitor", line_str);
callback(JSON.parse(line_str));
}
}
})
.catch((error, content) => {
Expand All @@ -55,12 +66,14 @@ function connect(address, system) {
options = options || {};
http.request(options)
.then(result => {
debug(system, `call ${id} result:`, JSON.stringify(result));
resolve(result);
const text = decoder.decode(result);
debug(system, `call ${id} result:`, text);
resolve(text);
})
.catch((error, content) => {
debug(system, `call ${id} error:`, JSON.stringify(error), "content", JSON.stringify(content));
manage_error(reject, error, content);
const text = decoder.decode(content);
debug(system, `call ${id} error:`, JSON.stringify(error), "content", text);
manage_error(reject, error, text);
});
});
};
Expand Down

0 comments on commit 346d0c3

Please sign in to comment.