mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-09-05 13:11:33 +00:00
use buffer protocol in WSGI response
This commit is contained in:
@@ -156,6 +156,8 @@ struct uwsgi_option uwsgi_python_options[] = {
|
||||
{"wsgi-env-behavior", required_argument, 0, "set the strategy for allocating/deallocating the WSGI env", uwsgi_opt_set_str, &up.wsgi_env_behaviour, 0},
|
||||
{"start_response-nodelay", no_argument, 0, "send WSGI http headers as soon as possible (PEP violation)", uwsgi_opt_true, &up.start_response_nodelay, 0},
|
||||
|
||||
{"wsgi-strict", no_argument, 0, "expect the WSGI callable to return ONLY strings (python 2.x) or bytes (python 3.x)", uwsgi_opt_true, &up.wsgi_strict, 0},
|
||||
|
||||
{"python-version", no_argument, 0, "report python version", uwsgi_opt_pyver, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
@@ -180,6 +180,7 @@ struct uwsgi_python {
|
||||
int start_response_nodelay;
|
||||
|
||||
char *programname;
|
||||
int wsgi_strict;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,57 @@ extern struct uwsgi_python up;
|
||||
extern struct uwsgi_plugin python_plugin;
|
||||
extern PyTypeObject uwsgi_InputType;
|
||||
|
||||
/*
|
||||
|
||||
Albeit PEP 333/3333 is clear about what kind of return object we must
|
||||
expect from a WSGI callable, we use the buffer api to optimize for lower-level
|
||||
returns type: bytes, bytearray, array.array
|
||||
|
||||
the "strict" can behavhiour can be forced with --wsgi-strict
|
||||
|
||||
*/
|
||||
|
||||
int uwsgi_python_send_body(struct wsgi_request *wsgi_req, PyObject *chunk) {
|
||||
char *content = NULL;
|
||||
size_t content_len = 0;
|
||||
if (!up.wsgi_strict) {
|
||||
#if defined(PYTHREE) || defined(Py_TPFLAGS_HAVE_NEWBUFFER)
|
||||
if (PyObject_CheckBuffer(chunk)) {
|
||||
Py_buffer pbuf;
|
||||
if (!PyObject_GetBuffer(chunk, &pbuf, PyBUF_SIMPLE)) {
|
||||
content = (char *) pbuf.buf;
|
||||
content_len = (size_t) pbuf.len;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (PyObject_CheckReadBuffer(chunk)) {
|
||||
if (!PyObject_AsCharBuffer(chunk, (const char **) &content, (Py_ssize_t *) &content_len)) {
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// fallback
|
||||
if (PyString_Check(chunk)) {
|
||||
content = PyString_AsString(chunk);
|
||||
content_len = PyString_Size(chunk);
|
||||
}
|
||||
|
||||
found:
|
||||
if (content) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_response_write_body_do(wsgi_req, content, content_len);
|
||||
UWSGI_GET_GIL
|
||||
uwsgi_py_check_write_errors {
|
||||
uwsgi_py_write_exception(wsgi_req);
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
this is a hack for supporting non-file object passed to wsgi.file_wrapper
|
||||
*/
|
||||
@@ -169,19 +220,10 @@ int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
|
||||
PyObject *pychunk;
|
||||
|
||||
// return or yield ?
|
||||
if (PyString_Check((PyObject *)wsgi_req->async_result)) {
|
||||
char *content = PyString_AsString((PyObject *)wsgi_req->async_result);
|
||||
size_t content_len = PyString_Size((PyObject *)wsgi_req->async_result);
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_response_write_body_do(wsgi_req, content, content_len);
|
||||
UWSGI_GET_GIL
|
||||
uwsgi_py_check_write_errors {
|
||||
uwsgi_py_write_exception(wsgi_req);
|
||||
}
|
||||
if (uwsgi_python_send_body(wsgi_req, (PyObject *)wsgi_req->async_result)) {
|
||||
goto clear;
|
||||
}
|
||||
|
||||
|
||||
if (wsgi_req->sendfile_obj == wsgi_req->async_result) {
|
||||
if (wsgi_req->sendfile_fd >= 0) {
|
||||
UWSGI_RELEASE_GIL
|
||||
@@ -222,19 +264,13 @@ exception:
|
||||
|
||||
|
||||
|
||||
if (PyString_Check(pychunk)) {
|
||||
char *content = PyString_AsString(pychunk);
|
||||
size_t content_len = PyString_Size(pychunk);
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_response_write_body_do(wsgi_req, content, content_len);
|
||||
UWSGI_GET_GIL
|
||||
uwsgi_py_check_write_errors {
|
||||
uwsgi_py_write_exception(wsgi_req);
|
||||
int ret = uwsgi_python_send_body(wsgi_req, pychunk);
|
||||
if (ret != 0) {
|
||||
if (ret < 0) {
|
||||
Py_DECREF(pychunk);
|
||||
goto clear;
|
||||
}
|
||||
}
|
||||
|
||||
else if (wsgi_req->sendfile_obj == pychunk) {
|
||||
if (wsgi_req->sendfile_fd >= 0) {
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
Reference in New Issue
Block a user