Deleted
Added
nxt_python_asgi.c (1682:2de7799a8749) | nxt_python_asgi.c (1697:73a335d2911d) |
---|---|
1 2/* 3 * Copyright (C) NGINX, Inc. 4 */ 5 6 7#include <python/nxt_python.h> 8 9#if (NXT_HAVE_ASGI) 10 11#include <nxt_main.h> 12#include <nxt_unit.h> 13#include <nxt_unit_request.h> 14#include <nxt_unit_response.h> 15#include <python/nxt_python_asgi.h> 16#include <python/nxt_python_asgi_str.h> 17 18 | 1 2/* 3 * Copyright (C) NGINX, Inc. 4 */ 5 6 7#include <python/nxt_python.h> 8 9#if (NXT_HAVE_ASGI) 10 11#include <nxt_main.h> 12#include <nxt_unit.h> 13#include <nxt_unit_request.h> 14#include <nxt_unit_response.h> 15#include <python/nxt_python_asgi.h> 16#include <python/nxt_python_asgi_str.h> 17 18 |
19static PyObject *nxt_python_asgi_get_func(PyObject *obj); |
|
19static int nxt_python_asgi_ctx_data_alloc(void **pdata); 20static void nxt_python_asgi_ctx_data_free(void *data); 21static int nxt_python_asgi_startup(void *data); 22static int nxt_python_asgi_run(nxt_unit_ctx_t *ctx); 23 24static void nxt_py_asgi_remove_reader(nxt_unit_ctx_t *ctx, 25 nxt_unit_port_t *port); 26static void nxt_py_asgi_request_handler(nxt_unit_request_info_t *req); --- 10 unchanged lines hidden (view full) --- 37static void nxt_py_asgi_remove_port(nxt_unit_t *lib, nxt_unit_port_t *port); 38static void nxt_py_asgi_quit(nxt_unit_ctx_t *ctx); 39static void nxt_py_asgi_shm_ack_handler(nxt_unit_ctx_t *ctx); 40 41static PyObject *nxt_py_asgi_port_read(PyObject *self, PyObject *args); 42static void nxt_python_asgi_done(void); 43 44 | 20static int nxt_python_asgi_ctx_data_alloc(void **pdata); 21static void nxt_python_asgi_ctx_data_free(void *data); 22static int nxt_python_asgi_startup(void *data); 23static int nxt_python_asgi_run(nxt_unit_ctx_t *ctx); 24 25static void nxt_py_asgi_remove_reader(nxt_unit_ctx_t *ctx, 26 nxt_unit_port_t *port); 27static void nxt_py_asgi_request_handler(nxt_unit_request_info_t *req); --- 10 unchanged lines hidden (view full) --- 38static void nxt_py_asgi_remove_port(nxt_unit_t *lib, nxt_unit_port_t *port); 39static void nxt_py_asgi_quit(nxt_unit_ctx_t *ctx); 40static void nxt_py_asgi_shm_ack_handler(nxt_unit_ctx_t *ctx); 41 42static PyObject *nxt_py_asgi_port_read(PyObject *self, PyObject *args); 43static void nxt_python_asgi_done(void); 44 45 |
46int nxt_py_asgi_legacy; |
|
45static PyObject *nxt_py_port_read; 46static nxt_unit_port_t *nxt_py_shared_port; 47 48static PyMethodDef nxt_py_port_read_method = 49 {"unit_port_read", nxt_py_asgi_port_read, METH_VARARGS, ""}; 50 51static nxt_python_proto_t nxt_py_asgi_proto = { 52 .ctx_data_alloc = nxt_python_asgi_ctx_data_alloc, --- 6 unchanged lines hidden (view full) --- 59 60#define NXT_UNIT_HASH_WS_PROTOCOL 0xED0A 61 62 63int 64nxt_python_asgi_check(PyObject *obj) 65{ 66 int res; | 47static PyObject *nxt_py_port_read; 48static nxt_unit_port_t *nxt_py_shared_port; 49 50static PyMethodDef nxt_py_port_read_method = 51 {"unit_port_read", nxt_py_asgi_port_read, METH_VARARGS, ""}; 52 53static nxt_python_proto_t nxt_py_asgi_proto = { 54 .ctx_data_alloc = nxt_python_asgi_ctx_data_alloc, --- 6 unchanged lines hidden (view full) --- 61 62#define NXT_UNIT_HASH_WS_PROTOCOL 0xED0A 63 64 65int 66nxt_python_asgi_check(PyObject *obj) 67{ 68 int res; |
67 PyObject *call; | 69 PyObject *func; |
68 PyCodeObject *code; 69 | 70 PyCodeObject *code; 71 |
70 if (PyFunction_Check(obj)) { 71 code = (PyCodeObject *) PyFunction_GET_CODE(obj); | 72 func = nxt_python_asgi_get_func(obj); |
72 | 73 |
73 return (code->co_flags & CO_COROUTINE) != 0; | 74 if (func == NULL) { 75 return 0; |
74 } 75 | 76 } 77 |
78 code = (PyCodeObject *) PyFunction_GET_CODE(func); 79 80 nxt_unit_debug(NULL, "asgi_check: callable is %sa coroutine function with " 81 "%d argument(s)", 82 (code->co_flags & CO_COROUTINE) != 0 ? "" : "not ", 83 code->co_argcount); 84 85 res = (code->co_flags & CO_COROUTINE) != 0 || code->co_argcount == 1; 86 87 Py_DECREF(func); 88 89 return res; 90} 91 92 93static PyObject * 94nxt_python_asgi_get_func(PyObject *obj) 95{ 96 PyObject *call; 97 98 if (PyFunction_Check(obj)) { 99 Py_INCREF(obj); 100 return obj; 101 } 102 |
|
76 if (PyMethod_Check(obj)) { 77 obj = PyMethod_GET_FUNCTION(obj); 78 | 103 if (PyMethod_Check(obj)) { 104 obj = PyMethod_GET_FUNCTION(obj); 105 |
79 code = (PyCodeObject *) PyFunction_GET_CODE(obj); 80 81 return (code->co_flags & CO_COROUTINE) != 0; | 106 Py_INCREF(obj); 107 return obj; |
82 } 83 84 call = PyObject_GetAttrString(obj, "__call__"); 85 86 if (call == NULL) { | 108 } 109 110 call = PyObject_GetAttrString(obj, "__call__"); 111 112 if (call == NULL) { |
87 return 0; | 113 return NULL; |
88 } 89 90 if (PyFunction_Check(call)) { | 114 } 115 116 if (PyFunction_Check(call)) { |
91 code = (PyCodeObject *) PyFunction_GET_CODE(call); | 117 return call; 118 } |
92 | 119 |
93 res = (code->co_flags & CO_COROUTINE) != 0; | 120 if (PyMethod_Check(call)) { 121 obj = PyMethod_GET_FUNCTION(call); |
94 | 122 |
95 } else { 96 if (PyMethod_Check(call)) { 97 obj = PyMethod_GET_FUNCTION(call); | 123 Py_INCREF(obj); 124 Py_DECREF(call); |
98 | 125 |
99 code = (PyCodeObject *) PyFunction_GET_CODE(obj); 100 101 res = (code->co_flags & CO_COROUTINE) != 0; 102 103 } else { 104 res = 0; 105 } | 126 return obj; |
106 } 107 108 Py_DECREF(call); 109 | 127 } 128 129 Py_DECREF(call); 130 |
110 return res; | 131 return NULL; |
111} 112 113 114int 115nxt_python_asgi_init(nxt_unit_init_t *init, nxt_python_proto_t *proto) 116{ | 132} 133 134 135int 136nxt_python_asgi_init(nxt_unit_init_t *init, nxt_python_proto_t *proto) 137{ |
138 PyObject *func; 139 PyCodeObject *code; 140 |
|
117 nxt_unit_debug(NULL, "asgi_init"); 118 119 if (nxt_slow_path(nxt_py_asgi_str_init() != NXT_UNIT_OK)) { 120 nxt_unit_alert(NULL, "Python failed to init string objects"); 121 return NXT_UNIT_ERROR; 122 } 123 124 nxt_py_port_read = PyCFunction_New(&nxt_py_port_read_method, NULL); --- 6 unchanged lines hidden (view full) --- 131 if (nxt_slow_path(nxt_py_asgi_http_init() == NXT_UNIT_ERROR)) { 132 return NXT_UNIT_ERROR; 133 } 134 135 if (nxt_slow_path(nxt_py_asgi_websocket_init() == NXT_UNIT_ERROR)) { 136 return NXT_UNIT_ERROR; 137 } 138 | 141 nxt_unit_debug(NULL, "asgi_init"); 142 143 if (nxt_slow_path(nxt_py_asgi_str_init() != NXT_UNIT_OK)) { 144 nxt_unit_alert(NULL, "Python failed to init string objects"); 145 return NXT_UNIT_ERROR; 146 } 147 148 nxt_py_port_read = PyCFunction_New(&nxt_py_port_read_method, NULL); --- 6 unchanged lines hidden (view full) --- 155 if (nxt_slow_path(nxt_py_asgi_http_init() == NXT_UNIT_ERROR)) { 156 return NXT_UNIT_ERROR; 157 } 158 159 if (nxt_slow_path(nxt_py_asgi_websocket_init() == NXT_UNIT_ERROR)) { 160 return NXT_UNIT_ERROR; 161 } 162 |
163 func = nxt_python_asgi_get_func(nxt_py_application); 164 if (nxt_slow_path(func == NULL)) { 165 nxt_unit_alert(NULL, "Python cannot find function for callable"); 166 return NXT_UNIT_ERROR; 167 } 168 169 code = (PyCodeObject *) PyFunction_GET_CODE(func); 170 171 if ((code->co_flags & CO_COROUTINE) == 0) { 172 nxt_unit_debug(NULL, "asgi: callable is not a coroutine function " 173 "switching to legacy mode"); 174 nxt_py_asgi_legacy = 1; 175 } 176 177 Py_DECREF(func); 178 |
|
139 init->callbacks.request_handler = nxt_py_asgi_request_handler; 140 init->callbacks.data_handler = nxt_py_asgi_http_data_handler; 141 init->callbacks.websocket_handler = nxt_py_asgi_websocket_handler; 142 init->callbacks.close_handler = nxt_py_asgi_websocket_close_handler; 143 init->callbacks.quit = nxt_py_asgi_quit; 144 init->callbacks.shm_ack_handler = nxt_py_asgi_shm_ack_handler; 145 init->callbacks.add_port = nxt_py_asgi_add_port; 146 init->callbacks.remove_port = nxt_py_asgi_remove_port; --- 214 unchanged lines hidden (view full) --- 361 Py_DECREF(fd); 362} 363 364 365static void 366nxt_py_asgi_request_handler(nxt_unit_request_info_t *req) 367{ 368 PyObject *scope, *res, *task, *receive, *send, *done, *asgi; | 179 init->callbacks.request_handler = nxt_py_asgi_request_handler; 180 init->callbacks.data_handler = nxt_py_asgi_http_data_handler; 181 init->callbacks.websocket_handler = nxt_py_asgi_websocket_handler; 182 init->callbacks.close_handler = nxt_py_asgi_websocket_close_handler; 183 init->callbacks.quit = nxt_py_asgi_quit; 184 init->callbacks.shm_ack_handler = nxt_py_asgi_shm_ack_handler; 185 init->callbacks.add_port = nxt_py_asgi_add_port; 186 init->callbacks.remove_port = nxt_py_asgi_remove_port; --- 214 unchanged lines hidden (view full) --- 401 Py_DECREF(fd); 402} 403 404 405static void 406nxt_py_asgi_request_handler(nxt_unit_request_info_t *req) 407{ 408 PyObject *scope, *res, *task, *receive, *send, *done, *asgi; |
409 PyObject *stage2; |
|
369 nxt_py_asgi_ctx_data_t *ctx_data; 370 371 if (req->request->websocket_handshake) { 372 asgi = nxt_py_asgi_websocket_create(req); 373 374 } else { 375 asgi = nxt_py_asgi_http_create(req); 376 } --- 33 unchanged lines hidden (view full) --- 410 if (nxt_slow_path(scope == NULL)) { 411 nxt_unit_request_done(req, NXT_UNIT_ERROR); 412 413 goto release_done; 414 } 415 416 req->data = asgi; 417 | 410 nxt_py_asgi_ctx_data_t *ctx_data; 411 412 if (req->request->websocket_handshake) { 413 asgi = nxt_py_asgi_websocket_create(req); 414 415 } else { 416 asgi = nxt_py_asgi_http_create(req); 417 } --- 33 unchanged lines hidden (view full) --- 451 if (nxt_slow_path(scope == NULL)) { 452 nxt_unit_request_done(req, NXT_UNIT_ERROR); 453 454 goto release_done; 455 } 456 457 req->data = asgi; 458 |
418 res = PyObject_CallFunctionObjArgs(nxt_py_application, 419 scope, receive, send, NULL); | 459 if (!nxt_py_asgi_legacy) { 460 nxt_unit_req_debug(req, "Python call ASGI 3.0 application"); 461 462 res = PyObject_CallFunctionObjArgs(nxt_py_application, 463 scope, receive, send, NULL); 464 465 } else { 466 nxt_unit_req_debug(req, "Python call legacy application"); 467 468 res = PyObject_CallFunctionObjArgs(nxt_py_application, scope, NULL); 469 470 if (nxt_slow_path(res == NULL)) { 471 nxt_unit_req_error(req, "Python failed to call legacy app stage1"); 472 nxt_python_print_exception(); 473 nxt_unit_request_done(req, NXT_UNIT_ERROR); 474 475 goto release_scope; 476 } 477 478 if (nxt_slow_path(PyCallable_Check(res) == 0)) { 479 nxt_unit_req_error(req, 480 "Legacy ASGI application returns not a callable"); 481 nxt_unit_request_done(req, NXT_UNIT_ERROR); 482 483 Py_DECREF(res); 484 485 goto release_scope; 486 } 487 488 stage2 = res; 489 490 res = PyObject_CallFunctionObjArgs(stage2, receive, send, NULL); 491 492 Py_DECREF(stage2); 493 } 494 |
420 if (nxt_slow_path(res == NULL)) { 421 nxt_unit_req_error(req, "Python failed to call the application"); 422 nxt_python_print_exception(); 423 nxt_unit_request_done(req, NXT_UNIT_ERROR); 424 425 goto release_scope; 426 } 427 --- 1015 unchanged lines hidden --- | 495 if (nxt_slow_path(res == NULL)) { 496 nxt_unit_req_error(req, "Python failed to call the application"); 497 nxt_python_print_exception(); 498 nxt_unit_request_done(req, NXT_UNIT_ERROR); 499 500 goto release_scope; 501 } 502 --- 1015 unchanged lines hidden --- |