[PATCH] suricatta/wfx: return HTTP response information

16 views
Skip to first unread message

Cirujano Cuesta, Silvano

unread,
May 22, 2026, 7:32:37 AM (14 days ago) May 22
to swup...@googlegroups.com, Zheng, Xiyue
Some HTTP requests might return some unexpected codes (outside of the
200-299 range) that are not really errors, but demand special treatment
on the client side.

Examples of these codes are:
- Most in the 300-399 range (redirects, temporary unavailability,...)
- Many in the 400-499 range (authentication, different client-behavior
expected,...)

The problem to give the requests the needed special treatment is that
`suricatta.download` and `suricatta.install` are not returning neither
the response codes nor the response headers that might provide further
information on how to do it.

This patch make `suricatta.download` and `suricatta.install` return any
available HTTP status code and response headers.

wfx client dumps all HTTP status codes and response headers on debug
mode.

This patch is a non-breaking change as it (for now) just logs the
returned HTTP status code and response headers.

Signed-off-by: Silvano Cirujano Cuesta <silvano.cir...@siemens.com>
Co-authored-by: Xiyue Zheng <xiyue...@siemens.com>
---
suricatta/server_lua.c | 31 ++++++++++++++++++++++++++++---
suricatta/server_wfx.lua | 20 ++++++++++++++++++--
suricatta/suricatta.lua | 11 +++++++++++
3 files changed, 57 insertions(+), 5 deletions(-)

diff --git a/suricatta/server_lua.c b/suricatta/server_lua.c
index b1e559c9..cb6348d1 100644
--- a/suricatta/server_lua.c
+++ b/suricatta/server_lua.c
@@ -1043,6 +1043,7 @@ static void join_progress_threads(pthread_t *thread, const char *thread_name)
* @return [Lua] True, or, in case of error, nil.
* [Lua] A suricatta.status value.
* [Lua] Table with messages in case of error, else empty Table.
+ * [Lua] Table with HTTP response code and headers.
* @see lua_suricatta_{install,download}() for parameter details.
*
* @param L The Lua state.
@@ -1130,6 +1131,11 @@ static void do_install(lua_State *L, int fdout)
callback_data.thread_offloader = &_thread_progress_offloader;
}

+ /* Setup received HTTP headers dict. */
+ struct dict received_headers;
+ LIST_INIT(&received_headers);
+ channel_data.received_headers = &received_headers;
+
/* Perform the operation.... */
server_op_res_t result = map_channel_retcode(
udc->channel->get_file(udc->channel, (void *)&channel_data));
@@ -1166,11 +1172,27 @@ static void do_install(lua_State *L, int fdout)
ipc_journal = NULL;
}

+ lua_newtable(L);
+ push_to_table(L, "http_response_code", channel_data.http_response_code);
+ lua_pushstring(L, "received_headers");
+ lua_newtable(L);
+ if (!LIST_EMPTY(channel_data.received_headers)) {
+ struct dict_entry *entry;
+ LIST_FOREACH(entry, channel_data.received_headers, next) {
+ lua_pushstring(L, dict_entry_get_key(entry));
+ lua_pushstring(L, dict_entry_get_value(entry));
+ lua_settable(L, -3);
+ }
+ }
+ lua_settable(L, -3);
+ dict_drop_db(&received_headers);
+
goto done;
error:
lua_pushnil(L);
lua_pushinteger(L, SERVER_EINIT);
lua_newtable(L);
+ lua_newtable(L);
done:
if (callback_data.progress_msgq_lock) {
if (pthread_mutex_destroy(callback_data.progress_msgq_lock) != 0) {
@@ -1197,12 +1219,13 @@ done:
* @return [Lua] True, or, in case of error, nil.
* [Lua] A suricatta.status value.
* [Lua] Table with messages in case of error, else empty Table.
+ * [Lua] Table with HTTP response codes and headers.
*/
static int lua_suricatta_install(lua_State *L)
{
luaL_checktype(L, -1, LUA_TTABLE);
do_install(L, -1);
- return 3;
+ return 4;
}


@@ -1214,6 +1237,7 @@ static int lua_suricatta_install(lua_State *L)
* @return [Lua] True, or, in case of error, nil.
* [Lua] A suricatta.status value.
* [Lua] Table with messages in case of error, else empty Table.
+ * [Lua] Table with HTTP response codes and headers.
*/
static int lua_suricatta_download(lua_State *L)
{
@@ -1228,12 +1252,13 @@ static int lua_suricatta_download(lua_State *L)
lua_pushnil(L);
lua_pushinteger(L, SERVER_EINIT);
lua_newtable(L);
- return 3;
+ lua_newtable(L);
+ return 4;
}
lua_pop(L, 1);
do_install(L, fdout);
(void)close(fdout);
- return 3;
+ return 4;
}


diff --git a/suricatta/server_wfx.lua b/suricatta/server_wfx.lua
index 9d67d3c4..00ace3ef 100644
--- a/suricatta/server_wfx.lua
+++ b/suricatta/server_wfx.lua
@@ -1330,7 +1330,15 @@ M.job.workflow.dispatch:set(
artifact.name,
source_uri
)
- local res, _, updatelog = suricatta.download({ channel = M.channel.main, url = source_uri }, target_uri)
+ local res, _, updatelog, response = suricatta.download({ channel = M.channel.main, url = source_uri }, target_uri)
+ if response ~= {} then
+ suricatta.notify.trace("Got HTTP response code %d from server.", response.http_response_code)
+ if response.received_headers then
+ for k, v in pairs(response.received_headers) do
+ suricatta.notify.trace("Got HTTP response header: %s = %s", k, v)
+ end
+ end
+ end
if not res then
local msg = ("Error downloading artifact %d/%d."):format(count, #job.definition.artifacts)
suricatta.notify.error(msg)
@@ -1511,11 +1519,19 @@ M.job.workflow.dispatch:set(
artifact.name,
source_uri
)
- local res, _, updatelog = suricatta.install({
+ local res, _, updatelog, response = suricatta.install({
channel = M.channel.main,
url = source_uri,
dry_run = job.definition:is_dry_run()
})
+ if response ~= {} then
+ suricatta.notify.trace("Got HTTP response code %d from server.", response.http_response_code)
+ if response.received_headers then
+ for k, v in pairs(response.received_headers) do
+ suricatta.notify.trace("Got HTTP response header: %s = %s", k, v)
+ end
+ end
+ end
-- Unconditionally remove the artifact file ignoring errors, e.g., if run in streaming mode.
os.remove(("%s%s_%d.swu"):format(suricatta.get_tmpdir(), job.id, count))
if not res then
diff --git a/suricatta/suricatta.lua b/suricatta/suricatta.lua
index 1ffac879..01020759 100644
--- a/suricatta/suricatta.lua
+++ b/suricatta/suricatta.lua
@@ -274,6 +274,15 @@ suricatta.channel = {
--- @field drain_messages boolean | nil Whether to flush all progress messages or only those while in-flight operation (default)
--- @field ∈ suricatta.channel.options | nil Channel options to override for this operation

+--- Channel HTTP response table.
+--
+-- HTTP response information in return of a channel operation.
+--
+--- @class suricatta.channel_operation_response
+--- @field http_response_code number
+--- @field received_headers table<string, string>
+
+
--- Install an update artifact from remote server or local file.
--
-- If the protocol specified in Table `install_channel`'s `url` field is `file://`,
@@ -286,6 +295,7 @@ suricatta.channel = {
--- @return boolean # Whether operation was successful or not
--- @return suricatta.status # Suricatta return code
--- @return table<number, string> # Error messages, if any
+--- @return suricatta.channel_operation_response # if `nocheckanswer` is not set, HTTP response information, if any
suricatta.install = function(install_channel) end

--- Download an update artifact from remote server.
@@ -300,6 +310,7 @@ suricatta.install = function(install_channel) end
--- @return boolean # Whether operation was successful or not
--- @return suricatta.status # Suricatta return code
--- @return table<number, string> # Error messages, if any
+--- @return suricatta.channel_operation_response # if `nocheckanswer` is not set, HTTP response information, if any
suricatta.download = function(download_channel, localpath) end


--
2.50.1

Stefano Babic

unread,
May 26, 2026, 6:40:53 AM (10 days ago) May 26
to Cirujano Cuesta, Silvano, swup...@googlegroups.com, Zheng, Xiyue
Applied to -master, thanks !

Best regards,
Stefano Babic

--
_______________________________________________________________________
Nabla Software Engineering GmbH
Hirschstr. 111A | 86156 Augsburg | Tel: +49 821 45592596
Geschäftsführer : Stefano Babic | HRB 40522 Augsburg
E-Mail: sba...@nabladev.com

Reply all
Reply to author
Forward
0 new messages