[PATCH] mongoose_interface: Fix invalid http 200 response in upload endpoint

20 views
Skip to first unread message

David Alonso de la Torre

unread,
Jan 25, 2026, 4:28:56 PM (7 days ago) Jan 25
to swup...@googlegroups.com, David Alonso de la Torre
* Extract upload http 200 reply serialization into mongoose_upload_ok_reply
* Add test_upload_ok_reply_format
* Fix mongoose_upload_ok_reply http 200 reply serialization

Signed-off-by: David Alonso de la Torre <david...@gmail.com>
---
include/mongoose_interface.h | 7 ++++
mongoose/mongoose_interface.c | 17 +++++---
test/Makefile | 1 +
test/test_mongoose_upload.c | 79 +++++++++++++++++++++++++++++++++++
4 files changed, 98 insertions(+), 6 deletions(-)
create mode 100644 test/test_mongoose_upload.c

diff --git a/include/mongoose_interface.h b/include/mongoose_interface.h
index 3ed7b4fb..376063a8 100644
--- a/include/mongoose_interface.h
+++ b/include/mongoose_interface.h
@@ -7,6 +7,11 @@

#pragma once

+#include <stddef.h>
+
+struct mg_connection;
+struct mg_str;
+
/*
* Max number of command line options
* to be passed to the mongoose webserver
@@ -18,3 +23,5 @@
int start_mongoose(const char *cfgfname, int argc, char *argv[]);

void mongoose_print_help(void);
+void mongoose_upload_ok_reply(struct mg_connection *nc,
+ const struct mg_str *filename, size_t len);
diff --git a/mongoose/mongoose_interface.c b/mongoose/mongoose_interface.c
index 729862e6..093dc292 100644
--- a/mongoose/mongoose_interface.c
+++ b/mongoose/mongoose_interface.c
@@ -550,6 +550,16 @@ static void timer_ev_handler(void *fn_data)
/*
* Code common to V1 and V2
*/
+void mongoose_upload_ok_reply(struct mg_connection *nc,
+ const struct mg_str *filename, size_t len)
+{
+ mg_http_reply(nc, 200,
+ "Content-Type: text/plain\r\n"
+ "Connection: close\r\n",
+ "Ok, %s - %d bytes.\r\n", filename->buf, (int)len);
+ nc->is_draining = 1;
+}
+
static void upload_handler(struct mg_connection *nc, int ev, void *ev_data)
{
struct mg_http_multipart *mp;
@@ -655,12 +665,7 @@ static void upload_handler(struct mg_connection *nc, int ev, void *ev_data)

ipc_end(fus->fd);

- mg_http_reply(nc, 200, "%s",
- "Content-Type: text/plain\r\n"
- "Connection: close");
- mg_send(nc, "\r\n", 2);
- mg_printf(nc, "Ok, %s - %d bytes.\r\n", mp->part.filename, (int) fus->len);
- nc->is_draining = 1;
+ mongoose_upload_ok_reply(nc, &mp->part.filename, fus->len);

mp->user_data = NULL;
mg_timer_free(&fus->c->mgr->timers, fus->timer);
diff --git a/test/Makefile b/test/Makefile
index 385efd85..578a3878 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -26,6 +26,7 @@ tests-$(CONFIG_SIGNED_IMAGES) += test_verify
endif
tests-$(CONFIG_SURICATTA_HAWKBIT) += test_json
tests-$(CONFIG_SURICATTA_HAWKBIT) += test_server_hawkbit
+tests-$(CONFIG_MONGOOSE) += test_mongoose_upload
tests-y += test_util
tests-$(CONFIG_CFI) += test_flash_handler

diff --git a/test/test_mongoose_upload.c b/test/test_mongoose_upload.c
new file mode 100644
index 00000000..4385a4b7
--- /dev/null
+++ b/test/test_mongoose_upload.c
@@ -0,0 +1,79 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "mongoose/mongoose.h"
+
+void mongoose_upload_ok_reply(struct mg_connection *nc,
+ const struct mg_str *filename, size_t len);
+
+static void test_upload_ok_reply_format(void **state)
+{
+ (void)state;
+
+ struct mg_connection nc;
+ const struct mg_str filename = mg_str("test.swu");
+ const char *expected_body = "Ok, test.swu - 20 bytes.\r\n";
+ const size_t filesize = 20;
+ char *buf;
+ char *body;
+ const char *line;
+ char *line_end;
+ int line_idx = 0;
+
+ memset(&nc, 0, sizeof(nc));
+
+ mongoose_upload_ok_reply(&nc, &filename, filesize);
+
+ // copy the data to a temporary buffer, to use null-terminated string functions
+ assert_non_null(nc.send.buf);
+ buf = malloc(nc.send.len + 1);
+ assert_non_null(buf);
+ memcpy(buf, nc.send.buf, nc.send.len);
+ buf[nc.send.len] = '\0';
+
+ line = buf;
+ while (true) {
+ line_end = strstr(line, "\r\n");
+ assert_non_null(line_end);
+ if (line_end == line) {
+ body = line_end + 2;
+ break;
+ }
+ *line_end = '\0';
+ if (line_idx == 0)
+ assert_string_equal(line, "HTTP/1.1 200 OK");
+ else if (line_idx == 1)
+ assert_string_equal(line, "Content-Type: text/plain");
+ else if (line_idx == 2)
+ assert_string_equal(line, "Connection: close");
+ else if (line_idx == 3)
+ assert_string_equal(line, "Content-Length: 26 ");
+ else
+ fail();
+ line_idx++;
+ line = line_end + 2;
+ }
+ assert_int_equal(line_idx, 4);
+ assert_string_equal(body, expected_body);
+
+ free(buf);
+ mg_iobuf_free(&nc.send);
+}
+
+int main(void)
+{
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_upload_ok_reply_format),
+ };
+
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
--
2.43.0

James Hilliard

unread,
Jan 26, 2026, 11:38:05 AM (7 days ago) Jan 26
to David Alonso de la Torre, swup...@googlegroups.com
On Sun, Jan 25, 2026 at 2:28 PM David Alonso de la Torre
<david...@gmail.com> wrote:
>
> * Extract upload http 200 reply serialization into mongoose_upload_ok_reply
> * Add test_upload_ok_reply_format
> * Fix mongoose_upload_ok_reply http 200 reply serialization
>
> Signed-off-by: David Alonso de la Torre <david...@gmail.com>
Reviewed-by: James Hilliard <james.h...@gmail.com.
> --
> You received this message because you are subscribed to the Google Groups "swupdate" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to swupdate+u...@googlegroups.com.
> To view this discussion visit https://groups.google.com/d/msgid/swupdate/20260125195749.9825-1-davidalto97%40gmail.com.

Stefano Babic

unread,
Jan 27, 2026, 8:55:26 AM (6 days ago) Jan 27
to David Alonso de la Torre, swup...@googlegroups.com
Hi David,

On 1/25/26 20:57, David Alonso de la Torre wrote:
> * Extract upload http 200 reply serialization into mongoose_upload_ok_reply
> * Add test_upload_ok_reply_format
> * Fix mongoose_upload_ok_reply http 200 reply serialization
>

I guess I need some more info, and I will ask you to rework the commit
message above with a more detailed explanation. Which is the real issue
you faced ? How you tested and how is the bug reproducible ?

Best regards,
Stefano Babic
Message has been deleted

David Alonso de la Torre

unread,
Jan 27, 2026, 1:59:44 PM (5 days ago) Jan 27
to Stefano Babic, swup...@googlegroups.com
Hello Stefano,

Sure. Please let me know which commit format you prefer and I will refactor.

Regarding the real issue, I use swupdate via meta-swupdate in a Yocto image, specifically the built-in swupdate mongoose server to upload the swu images using /upload endpoint.
Until recently, I've been working with swupdate 2019.xx and everything worked as expected. 
Recently, I've upgraded the system and noticed incorrect http format replies from the upload endpoint introduced  in swupdate 2022.12 when mongoose was migrated to v7. Specifically, it was introduced in this commit: https://github.com/sbabic/swupdate/commit/ce8702ce7e6589eaeb555fc74357d6c9adae9949

 
For testing, I've used curl. See the outputs as reference.
-
- swupdate 2019.xx 
$ curl -v --progress-bar -X POST "http://10.11.12.1:8090/upload"   -H "Accept: application/json"   -H "Content-Type: multipart/form-data"   -F "file=@$FILEPATH;filename=$FILENAME;type=application/octet-stream"
Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying 10.11.12.1:8090...
* Connected to 10.11.12.1 (10.11.12.1) port 8090
> POST /upload HTTP/1.1
> Host: 10.11.12.1:8090
> User-Agent: curl/8.5.0
> Accept: application/json
> Content-Length: 86715637
> Content-Type: multipart/form-data; boundary=------------------------4YdUs2sBH1JSihrprLSImI
> Expect: 100-continue
> 
* Done waiting for 100-continue
* We are completely uploaded and fine
< HTTP/1.1 200 OK
< Server: Mongoose/6.11
< Content-Type: text/plain
< Connection: close
< 
Ok, orca-image-swu-imx6ul-var-dart.rootfs.swu - 86715392 bytes.
- swupdate 2022.12 or newer:
curl -v --progress-bar -X POST "http://10.11.12.1:8090/upload"   -H "Accept: application/json"   -H "Content-Type: multipart/form-data"   -F "file=@$FILEPATH;filename=$FILENAME;type=application/octet-stream"
Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying 10.11.12.1:8090...
* Connected to 10.11.12.1 (10.11.12.1) port 8090
> POST /upload HTTP/1.1
> Host: 10.11.12.1:8090
> User-Agent: curl/8.5.0
> Accept: application/json
> Content-Length: 86715637
> Content-Type: multipart/form-data; boundary=------------------------iDbDdIx3bL4msqUy9I3cHe
> Expect: 100-continue
> 
* Done waiting for 100-continue
* We are completely uploaded and fine
< HTTP/1.1 200 OK
< %sContent-Length: 0000000043
* no chunk, no close, no size. Assume close to signal end
< 
Content-Type: text/plain
Connection: close
Ok, orca-image-swu-imx6ul-var-dart.rootfs.swu - 41 bytes.
* Closing connection

As you can see, the Content-Length header is wrongly formatted: " %sContent-Length: 0000000043", causing some http clients to fail.
The upload is successfully finished, but the http response is incorrect.

 You can see the curl commands that I've used for testing.

Please let me know if you need more information.

Regards,
David

Stefano Babic

unread,
Jan 28, 2026, 7:02:46 AM (5 days ago) Jan 28
to David Alonso de la Torre, Stefano Babic, swup...@googlegroups.com
Hi David,

On 1/27/26 19:59, David Alonso de la Torre wrote:
> Hello Stefano,
>
> Sure. Please let me know which commit format you prefer and I will refactor.
>
> Regarding the real issue, I use swupdate via meta-swupdate in a Yocto
> image, specifically the built-in swupdate mongoose server to upload the
> swu images using /upload endpoint.
> Until recently, I've been working with swupdate 2019.xx and everything
> worked as expected.
> Recently, I've upgraded the system and noticed incorrect http format
> replies from the upload endpoint introduced  in swupdate 2022.12 when
> mongoose was migrated to v7. Specifically, it was introduced in this
> commit: https://github.com/sbabic/swupdate/commit/
> ce8702ce7e6589eaeb555fc74357d6c9adae9949 <https://github.com/sbabic/
> swupdate/commit/ce8702ce7e6589eaeb555fc74357d6c9adae9949>
>
> For testing, I've used curl. See the outputs as reference.
> -
> - swupdate 2019.xx
>
> $ curl -v --progress-bar -X POST "http://10.11.12.1:8090/upload <http://10.11.12.1:8090/upload>" -H "Accept: application/json" -H "Content-Type: multipart/form-data" -F "file=@$FILEPATH;filename=$FILENAME;type=application/octet-stream"
> Note: Unnecessary use of -X or --request, POST is already inferred.
> * Trying 10.11.12.1:8090...
> * Connected to 10.11.12.1 (10.11.12.1) port 8090
>> POST /upload HTTP/1.1
>> Host: 10.11.12.1:8090 <http://10.11.12.1:8090/>
>> User-Agent: curl/8.5.0
>> Accept: application/json
>> Content-Length: 86715637
>> Content-Type: multipart/form-data; boundary=------------------------4YdUs2sBH1JSihrprLSImI
>> Expect: 100-continue
>>
> * Done waiting for 100-continue
> * We are completely uploaded and fine
> < HTTP/1.1 200 OK
> < Server: Mongoose/6.11
> < Content-Type: text/plain
> < Connection: close
> <
> Ok, orca-image-swu-imx6ul-var-dart.rootfs.swu - 86715392 bytes.
>
> - swupdate 2022.12 or newer:
>
> curl -v --progress-bar -X POST "http://10.11.12.1:8090/upload <http://10.11.12.1:8090/upload>" -H "Accept: application/json" -H "Content-Type: multipart/form-data" -F "file=@$FILEPATH;filename=$FILENAME;type=application/octet-stream"
> Note: Unnecessary use of -X or --request, POST is already inferred.
> * Trying 10.11.12.1:8090...
> * Connected to 10.11.12.1 (10.11.12.1) port 8090
>> POST /upload HTTP/1.1
>> Host: 10.11.12.1:8090 <http://10.11.12.1:8090/>
>> User-Agent: curl/8.5.0
>> Accept: application/json
>> Content-Length: 86715637
>> Content-Type: multipart/form-data; boundary=------------------------iDbDdIx3bL4msqUy9I3cHe
>> Expect: 100-continue
>>
> * Done waiting for 100-continue
> * We are completely uploaded and fine
> < HTTP/1.1 200 OK
> < %sContent-Length: 0000000043

Ok, I see this.

> * no chunk, no close, no size. Assume close to signal end
> <
> Content-Type: text/plain
> Connection: close
> Ok, orca-image-swu-imx6ul-var-dart.rootfs.swu - 41 bytes.
> * Closing connection
>
>
> As you can see, the Content-Length header is wrongly formatted: "
> %sContent-Length: 0000000043", causing some http clients to fail.
> The upload is successfully finished, but the http response is incorrect.
>
>  You can see the curl commands that I've used for testing.
>
> Please let me know if you need more information.

Ok, now it is clear. I would like you add this useful information and
reporting the broken answer from the server (so %sContent-Length:) into
the commit message, so that is tracked, else we do not know which bug
was closed. After that, I will merge it.

Best regards,
Stefano Babic

>
> Regards,
> David
>
> --
> You received this message because you are subscribed to the Google
> Groups "swupdate" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to swupdate+u...@googlegroups.com
> <mailto:swupdate+u...@googlegroups.com>.
> To view this discussion visit https://groups.google.com/d/msgid/
> swupdate/
> CAPnr%3DRcboOidvkuwhc6QStEH06rM1Pq53O88wgsHorw1%2BxTcrw%40mail.gmail.com
> <https://groups.google.com/d/msgid/swupdate/
> CAPnr%3DRcboOidvkuwhc6QStEH06rM1Pq53O88wgsHorw1%2BxTcrw%40mail.gmail.com?utm_medium=email&utm_source=footer>.

Reply all
Reply to author
Forward
0 new messages