On 6/16/21 8:04 PM, Jonas Smedegaard wrote: > [ replying via bugreport ] > > Quoting Thomas Goirand (2021-06-16 19:20:44) >> Can I NMU uwsgi as per the discussion with the release team? Should it >> be 2.0.19.1-7.1 or 2.0.19.1-8? Should I also open a merge request on >> Salsa? > > Yes, please use standard procedure for NMUs - i.e. release as -7.1 and > share the changes with nmudiff (not using salsa). > > > Thanks, > > - Jonas
Hi Jonas, Thanks for your trust. Please find the debdiff between 2.0.19.1-7 and 2.0.19.1-7.1 that I have just uploaded. I will remove the moreinfo tag of #989851 once the buildd are done with rebuilding -7.1. I'm changing the title to have #989851 reflect the NMU version rather than -8. Cheers, Thomas Goirand (zigo)
diff -Nru uwsgi-2.0.19.1/debian/changelog uwsgi-2.0.19.1/debian/changelog --- uwsgi-2.0.19.1/debian/changelog 2021-05-28 07:56:03.000000000 +0200 +++ uwsgi-2.0.19.1/debian/changelog 2021-06-11 11:08:33.000000000 +0200 @@ -1,3 +1,12 @@ +uwsgi (2.0.19.1-7.1) unstable; urgency=medium + + [ Thomas Goirand ] + * Non-maintainer upload. + * Add upstream patch to support Transfer-Encoding: chuncked, necessary for + OpenStack Glance and Swift over uwsgi. + + -- Thomas Goirand <z...@debian.org> Fri, 11 Jun 2021 11:08:33 +0200 + uwsgi (2.0.19.1-7) unstable; urgency=medium * add patch cherry-picked upstream diff -Nru uwsgi-2.0.19.1/debian/patches/Add_support_for_chunked_encoding.patch uwsgi-2.0.19.1/debian/patches/Add_support_for_chunked_encoding.patch --- uwsgi-2.0.19.1/debian/patches/Add_support_for_chunked_encoding.patch 1970-01-01 01:00:00.000000000 +0100 +++ uwsgi-2.0.19.1/debian/patches/Add_support_for_chunked_encoding.patch 2021-06-11 11:08:33.000000000 +0200 @@ -0,0 +1,241 @@ +Subject: preliminary implementation of #1428 + This implements support for transfer-encoding: chuncked +Author: Unbit <i...@unbit.it> +Date: Thu, 9 Nov 2017 16:40:44 +0100 +Last-Update: 2021-06-11 + +Index: uwsgi/core/chunked.c +=================================================================== +--- uwsgi.orig/core/chunked.c ++++ uwsgi/core/chunked.c +@@ -83,6 +83,83 @@ static ssize_t uwsgi_chunked_readline(st + + */ + ++struct uwsgi_buffer *uwsgi_chunked_read_smart(struct wsgi_request *wsgi_req, size_t len, int timeout) { ++ // check for buffer ++ if (!wsgi_req->body_chunked_buf) ++ wsgi_req->body_chunked_buf = uwsgi_buffer_new(uwsgi.page_size); ++ // first case: asking for all ++ if (!len) { ++ for(;;) { ++ size_t chunked_len = 0; ++ char *buf = uwsgi_chunked_read(wsgi_req, &chunked_len, timeout, 0); ++ if (chunked_len == 0) { ++ struct uwsgi_buffer *ret = uwsgi_buffer_new(wsgi_req->body_chunked_buf->pos); ++ if (uwsgi_buffer_append(ret, wsgi_req->body_chunked_buf->buf, wsgi_req->body_chunked_buf->pos)) { ++ uwsgi_buffer_destroy(ret); ++ return NULL; ++ } ++ uwsgi_buffer_decapitate(wsgi_req->body_chunked_buf, wsgi_req->body_chunked_buf->pos); ++ return ret; ++ } ++ if (uwsgi_buffer_append(wsgi_req->body_chunked_buf, buf, chunked_len)) { ++ return NULL; ++ } ++ } ++ } ++ ++ // asking for littler part ++ if (len <= wsgi_req->body_chunked_buf->pos) { ++ struct uwsgi_buffer *ret = uwsgi_buffer_new(len); ++ if (uwsgi_buffer_append(ret, wsgi_req->body_chunked_buf->buf, len)) { ++ uwsgi_buffer_destroy(ret); ++ return NULL; ++ } ++ uwsgi_buffer_decapitate(wsgi_req->body_chunked_buf, len); ++ return ret; ++ } ++ ++ // more data required ++ size_t remains = len; ++ struct uwsgi_buffer *ret = uwsgi_buffer_new(remains); ++ if (wsgi_req->body_chunked_buf->pos > 0) { ++ if (uwsgi_buffer_append(ret, wsgi_req->body_chunked_buf->buf, wsgi_req->body_chunked_buf->pos)) { ++ uwsgi_buffer_destroy(ret); ++ return NULL; ++ } ++ remains -= wsgi_req->body_chunked_buf->pos; ++ uwsgi_buffer_decapitate(wsgi_req->body_chunked_buf, wsgi_req->body_chunked_buf->pos); ++ } ++ ++ while(remains) { ++ size_t chunked_len = 0; ++ char *buf = uwsgi_chunked_read(wsgi_req, &chunked_len, timeout, 0); ++ if (chunked_len == 0) { ++ break; ++ } ++ if (uwsgi_buffer_append(wsgi_req->body_chunked_buf, buf, chunked_len)) { ++ uwsgi_buffer_destroy(ret); ++ return NULL; ++ } ++ ++ if (chunked_len > remains) { ++ if (uwsgi_buffer_append(ret, wsgi_req->body_chunked_buf->buf, wsgi_req->body_chunked_buf->pos - (chunked_len - remains))) { ++ uwsgi_buffer_destroy(ret); ++ return NULL; ++ } ++ uwsgi_buffer_decapitate(wsgi_req->body_chunked_buf, wsgi_req->body_chunked_buf->pos - (chunked_len - remains)); ++ return ret; ++ } ++ remains -= chunked_len; ++ } ++ ++ if (uwsgi_buffer_append(ret, wsgi_req->body_chunked_buf->buf, wsgi_req->body_chunked_buf->pos)) { ++ uwsgi_buffer_destroy(ret); ++ return NULL; ++ } ++ uwsgi_buffer_decapitate(wsgi_req->body_chunked_buf, wsgi_req->body_chunked_buf->pos); ++ return ret; ++} ++ + char *uwsgi_chunked_read(struct wsgi_request *wsgi_req, size_t *len, int timeout, int nb) { + + if (!wsgi_req->chunked_input_buf) { +Index: uwsgi/core/protocol.c +=================================================================== +--- uwsgi.orig/core/protocol.c ++++ uwsgi/core/protocol.c +@@ -560,6 +560,12 @@ static int uwsgi_proto_check_22(struct w + wsgi_req->scheme_len = len; + } + ++ if (!uwsgi_proto_key("HTTP_TRANSFER_ENCODING", 22)) { ++ if (!uwsgi_strnicmp(buf, len, "chunked", 7)) { ++ wsgi_req->body_is_chunked = 1; ++ } ++ } ++ + return 0; + } + +Index: uwsgi/core/utils.c +=================================================================== +--- uwsgi.orig/core/utils.c ++++ uwsgi/core/utils.c +@@ -1182,6 +1182,10 @@ void uwsgi_close_request(struct wsgi_req + uwsgi_buffer_destroy(wsgi_req->chunked_input_buf); + } + ++ if (wsgi_req->body_chunked_buf) { ++ uwsgi_buffer_destroy(wsgi_req->body_chunked_buf); ++ } ++ + // free websocket engine + if (wsgi_req->websocket_buf) { + uwsgi_buffer_destroy(wsgi_req->websocket_buf); +Index: uwsgi/plugins/python/python_plugin.c +=================================================================== +--- uwsgi.orig/plugins/python/python_plugin.c ++++ uwsgi/plugins/python/python_plugin.c +@@ -174,6 +174,8 @@ struct uwsgi_option uwsgi_python_options + + {"python-worker-override", required_argument, 0, "override worker with the specified python script", uwsgi_opt_set_str, &up.worker_override, 0}, + ++ {"wsgi-manage-chunked-input", no_argument, 0, "manage chunked input via the wsgi.input_terminated extension", uwsgi_opt_true, &up.wsgi_manage_chunked_input, 0}, ++ + {0, 0, 0, 0, 0, 0, 0}, + }; + +Index: uwsgi/plugins/python/uwsgi_python.h +=================================================================== +--- uwsgi.orig/plugins/python/uwsgi_python.h ++++ uwsgi/plugins/python/uwsgi_python.h +@@ -214,6 +214,8 @@ struct uwsgi_python { + int wsgi_disable_file_wrapper; + + char *worker_override; ++ ++ int wsgi_manage_chunked_input; + }; + + +Index: uwsgi/plugins/python/wsgi_handlers.c +=================================================================== +--- uwsgi.orig/plugins/python/wsgi_handlers.c ++++ uwsgi/plugins/python/wsgi_handlers.c +@@ -62,7 +62,20 @@ static PyObject *uwsgi_Input_read(uwsgi_ + ssize_t rlen = 0; + + UWSGI_RELEASE_GIL +- char *buf = uwsgi_request_body_read(wsgi_req, arg_len, &rlen); ++ char *buf = NULL; ++ if (wsgi_req->body_is_chunked && up.wsgi_manage_chunked_input) { ++ struct uwsgi_buffer *ubuf = uwsgi_chunked_read_smart(wsgi_req, arg_len, uwsgi.socket_timeout); ++ UWSGI_GET_GIL ++ if (!ubuf) { ++ return PyErr_Format(PyExc_IOError, "error during chunked read(%ld) on wsgi.input", arg_len); ++ } ++ PyObject *ret = PyString_FromStringAndSize(ubuf->buf, ubuf->pos); ++ uwsgi_buffer_destroy(ubuf); ++ return ret; ++ } ++ else { ++ buf = uwsgi_request_body_read(wsgi_req, arg_len, &rlen); ++ } + UWSGI_GET_GIL + if (buf == uwsgi.empty) { + return PyString_FromString(""); +Index: uwsgi/plugins/python/wsgi_subhandler.c +=================================================================== +--- uwsgi.orig/plugins/python/wsgi_subhandler.c ++++ uwsgi/plugins/python/wsgi_subhandler.c +@@ -179,6 +179,15 @@ void *uwsgi_request_subhandler_wsgi(stru + + PyDict_SetItemString(wsgi_req->async_environ, "wsgi.input", wsgi_req->async_input); + ++ if (up.wsgi_manage_chunked_input) { ++ if (wsgi_req->body_is_chunked) { ++ PyDict_SetItemString(wsgi_req->async_environ, "wsgi.input_terminated", Py_True); ++ } ++ else { ++ PyDict_SetItemString(wsgi_req->async_environ, "wsgi.input_terminated", Py_False); ++ } ++ } ++ + if (!up.wsgi_disable_file_wrapper) + PyDict_SetItemString(wsgi_req->async_environ, "wsgi.file_wrapper", wi->sendfile); + +Index: uwsgi/t/python/wsgi_chunked.py +=================================================================== +--- /dev/null ++++ uwsgi/t/python/wsgi_chunked.py +@@ -0,0 +1,16 @@ ++def application(environ, start_response): ++ print(environ) ++ start_response('200 OK', []) ++ if not environ['wsgi.input_terminated']: ++ return [] ++# print(environ['wsgi.input'].read()) ++ data = environ['wsgi.input'].read(2) ++ print(data) ++ data = environ['wsgi.input'].read(2) ++ print(data) ++ data = environ['wsgi.input'].read(2) ++ print(data) ++ data = environ['wsgi.input'].read(6) ++ print(data) ++ print(environ['wsgi.input'].read()) ++ return [data] +Index: uwsgi/uwsgi.h +=================================================================== +--- uwsgi.orig/uwsgi.h ++++ uwsgi/uwsgi.h +@@ -1617,6 +1617,9 @@ struct wsgi_request { + // used for protocol parsers requiring EOF signaling + int proto_parser_eof; + ++ int body_is_chunked; ++ struct uwsgi_buffer *body_chunked_buf; ++ + // 64bit range, deprecates size_t __range_from, __range_to + enum uwsgi_range range_parsed; + int64_t range_from; +@@ -4506,6 +4509,7 @@ struct uwsgi_buffer *uwsgi_websocket_rec + struct uwsgi_buffer *uwsgi_websocket_recv_nb(struct wsgi_request *); + + char *uwsgi_chunked_read(struct wsgi_request *, size_t *, int, int); ++struct uwsgi_buffer *uwsgi_chunked_read_smart(struct wsgi_request *, size_t, int); + + uint16_t uwsgi_be16(char *); + uint32_t uwsgi_be32(char *); diff -Nru uwsgi-2.0.19.1/debian/patches/series uwsgi-2.0.19.1/debian/patches/series --- uwsgi-2.0.19.1/debian/patches/series 2021-05-28 07:43:30.000000000 +0200 +++ uwsgi-2.0.19.1/debian/patches/series 2021-06-11 11:08:33.000000000 +0200 @@ -20,3 +20,4 @@ 1016_readline.patch 1017_python3-compat.patch 2001_ensure_verbose_build.patch +Add_support_for_chunked_encoding.patch