nxt_python_asgi_http.c (1717:fcd578736562) nxt_python_asgi_http.c (1916:2d7e54265010)
1
2/*
3 * Copyright (C) NGINX, Inc.
4 */
5
6
7#include <python/nxt_python.h>
8

--- 9 unchanged lines hidden (view full) ---

18typedef struct {
19 PyObject_HEAD
20 nxt_unit_request_info_t *req;
21 nxt_queue_link_t link;
22 PyObject *receive_future;
23 PyObject *send_future;
24 uint64_t content_length;
25 uint64_t bytes_sent;
1
2/*
3 * Copyright (C) NGINX, Inc.
4 */
5
6
7#include <python/nxt_python.h>
8

--- 9 unchanged lines hidden (view full) ---

18typedef struct {
19 PyObject_HEAD
20 nxt_unit_request_info_t *req;
21 nxt_queue_link_t link;
22 PyObject *receive_future;
23 PyObject *send_future;
24 uint64_t content_length;
25 uint64_t bytes_sent;
26 int complete;
27 int closed;
28 PyObject *send_body;
29 Py_ssize_t send_body_off;
26 PyObject *send_body;
27 Py_ssize_t send_body_off;
28 uint8_t complete;
29 uint8_t closed;
30 uint8_t empty_body_received;
30} nxt_py_asgi_http_t;
31
32
33static PyObject *nxt_py_asgi_http_receive(PyObject *self, PyObject *none);
34static PyObject *nxt_py_asgi_http_read_msg(nxt_py_asgi_http_t *http);
35static PyObject *nxt_py_asgi_http_send(PyObject *self, PyObject *dict);
36static PyObject *nxt_py_asgi_http_response_start(nxt_py_asgi_http_t *http,
37 PyObject *dict);
38static PyObject *nxt_py_asgi_http_response_body(nxt_py_asgi_http_t *http,
39 PyObject *dict);
31} nxt_py_asgi_http_t;
32
33
34static PyObject *nxt_py_asgi_http_receive(PyObject *self, PyObject *none);
35static PyObject *nxt_py_asgi_http_read_msg(nxt_py_asgi_http_t *http);
36static PyObject *nxt_py_asgi_http_send(PyObject *self, PyObject *dict);
37static PyObject *nxt_py_asgi_http_response_start(nxt_py_asgi_http_t *http,
38 PyObject *dict);
39static PyObject *nxt_py_asgi_http_response_body(nxt_py_asgi_http_t *http,
40 PyObject *dict);
41static void nxt_py_asgi_http_emit_disconnect(nxt_py_asgi_http_t *http);
40static PyObject *nxt_py_asgi_http_done(PyObject *self, PyObject *future);
41
42
43static PyMethodDef nxt_py_asgi_http_methods[] = {
44 { "receive", nxt_py_asgi_http_receive, METH_NOARGS, 0 },
45 { "send", nxt_py_asgi_http_send, METH_O, 0 },
46 { "_done", nxt_py_asgi_http_done, METH_O, 0 },
47 { NULL, NULL, 0, 0 }

--- 41 unchanged lines hidden (view full) ---

89 http = PyObject_New(nxt_py_asgi_http_t, &nxt_py_asgi_http_type);
90
91 if (nxt_fast_path(http != NULL)) {
92 http->req = req;
93 http->receive_future = NULL;
94 http->send_future = NULL;
95 http->content_length = -1;
96 http->bytes_sent = 0;
42static PyObject *nxt_py_asgi_http_done(PyObject *self, PyObject *future);
43
44
45static PyMethodDef nxt_py_asgi_http_methods[] = {
46 { "receive", nxt_py_asgi_http_receive, METH_NOARGS, 0 },
47 { "send", nxt_py_asgi_http_send, METH_O, 0 },
48 { "_done", nxt_py_asgi_http_done, METH_O, 0 },
49 { NULL, NULL, 0, 0 }

--- 41 unchanged lines hidden (view full) ---

91 http = PyObject_New(nxt_py_asgi_http_t, &nxt_py_asgi_http_type);
92
93 if (nxt_fast_path(http != NULL)) {
94 http->req = req;
95 http->receive_future = NULL;
96 http->send_future = NULL;
97 http->content_length = -1;
98 http->bytes_sent = 0;
97 http->complete = 0;
98 http->closed = 0;
99 http->send_body = NULL;
100 http->send_body_off = 0;
99 http->send_body = NULL;
100 http->send_body_off = 0;
101 http->complete = 0;
102 http->closed = 0;
103 http->empty_body_received = 0;
101 }
102
103 return (PyObject *) http;
104}
105
106
107static PyObject *
108nxt_py_asgi_http_receive(PyObject *self, PyObject *none)
109{
110 PyObject *msg, *future;
111 nxt_py_asgi_http_t *http;
112 nxt_py_asgi_ctx_data_t *ctx_data;
113 nxt_unit_request_info_t *req;
114
115 http = (nxt_py_asgi_http_t *) self;
116 req = http->req;
117
118 nxt_unit_req_debug(req, "asgi_http_receive");
119
104 }
105
106 return (PyObject *) http;
107}
108
109
110static PyObject *
111nxt_py_asgi_http_receive(PyObject *self, PyObject *none)
112{
113 PyObject *msg, *future;
114 nxt_py_asgi_http_t *http;
115 nxt_py_asgi_ctx_data_t *ctx_data;
116 nxt_unit_request_info_t *req;
117
118 http = (nxt_py_asgi_http_t *) self;
119 req = http->req;
120
121 nxt_unit_req_debug(req, "asgi_http_receive");
122
120 if (nxt_slow_path(http->closed || nxt_unit_response_is_sent(req))) {
123 if (nxt_slow_path(http->closed || http->complete )) {
121 msg = nxt_py_asgi_new_msg(req, nxt_py_http_disconnect_str);
122
123 } else {
124 msg = nxt_py_asgi_http_read_msg(http);
125 }
126
127 if (nxt_slow_path(msg == NULL)) {
128 return NULL;

--- 37 unchanged lines hidden (view full) ---

166 req = http->req;
167
168 size = req->content_length;
169
170 if (size > nxt_py_asgi_http_body_buf_size) {
171 size = nxt_py_asgi_http_body_buf_size;
172 }
173
124 msg = nxt_py_asgi_new_msg(req, nxt_py_http_disconnect_str);
125
126 } else {
127 msg = nxt_py_asgi_http_read_msg(http);
128 }
129
130 if (nxt_slow_path(msg == NULL)) {
131 return NULL;

--- 37 unchanged lines hidden (view full) ---

169 req = http->req;
170
171 size = req->content_length;
172
173 if (size > nxt_py_asgi_http_body_buf_size) {
174 size = nxt_py_asgi_http_body_buf_size;
175 }
176
177 if (size == 0) {
178 if (http->empty_body_received) {
179 Py_RETURN_NONE;
180 }
181
182 http->empty_body_received = 1;
183 }
184
174 if (size > 0) {
175 body = PyBytes_FromStringAndSize(NULL, size);
176 if (nxt_slow_path(body == NULL)) {
177 nxt_unit_req_alert(req, "Python failed to create body byte string");
178 nxt_python_print_exception();
179
180 return PyErr_Format(PyExc_RuntimeError,
181 "failed to create Bytes object");

--- 255 unchanged lines hidden (view full) ---

437 return PyErr_Format(PyExc_RuntimeError,
438 "failed to send response");
439 }
440 }
441 }
442
443 if (more_body == NULL || more_body == Py_False) {
444 http->complete = 1;
185 if (size > 0) {
186 body = PyBytes_FromStringAndSize(NULL, size);
187 if (nxt_slow_path(body == NULL)) {
188 nxt_unit_req_alert(req, "Python failed to create body byte string");
189 nxt_python_print_exception();
190
191 return PyErr_Format(PyExc_RuntimeError,
192 "failed to create Bytes object");

--- 255 unchanged lines hidden (view full) ---

448 return PyErr_Format(PyExc_RuntimeError,
449 "failed to send response");
450 }
451 }
452 }
453
454 if (more_body == NULL || more_body == Py_False) {
455 http->complete = 1;
456
457 nxt_py_asgi_http_emit_disconnect(http);
445 }
446
447 Py_INCREF(http);
448 return (PyObject *) http;
449}
450
451
458 }
459
460 Py_INCREF(http);
461 return (PyObject *) http;
462}
463
464
465static void
466nxt_py_asgi_http_emit_disconnect(nxt_py_asgi_http_t *http)
467{
468 PyObject *msg, *future, *res;
469
470 if (http->receive_future == NULL) {
471 return;
472 }
473
474 msg = nxt_py_asgi_new_msg(http->req, nxt_py_http_disconnect_str);
475 if (nxt_slow_path(msg == NULL)) {
476 return;
477 }
478
479 if (msg == Py_None) {
480 Py_DECREF(msg);
481 return;
482 }
483
484 future = http->receive_future;
485 http->receive_future = NULL;
486
487 res = PyObject_CallMethodObjArgs(future, nxt_py_set_result_str, msg, NULL);
488 if (nxt_slow_path(res == NULL)) {
489 nxt_unit_req_alert(http->req, "'set_result' call failed");
490 nxt_python_print_exception();
491 }
492
493 Py_XDECREF(res);
494 Py_DECREF(future);
495
496 Py_DECREF(msg);
497}
498
499
452void
453nxt_py_asgi_http_data_handler(nxt_unit_request_info_t *req)
454{
455 PyObject *msg, *future, *res;
456 nxt_py_asgi_http_t *http;
457
458 http = req->data;
459

--- 108 unchanged lines hidden (view full) ---

568
569 return NXT_UNIT_ERROR;
570}
571
572
573void
574nxt_py_asgi_http_close_handler(nxt_unit_request_info_t *req)
575{
500void
501nxt_py_asgi_http_data_handler(nxt_unit_request_info_t *req)
502{
503 PyObject *msg, *future, *res;
504 nxt_py_asgi_http_t *http;
505
506 http = req->data;
507

--- 108 unchanged lines hidden (view full) ---

616
617 return NXT_UNIT_ERROR;
618}
619
620
621void
622nxt_py_asgi_http_close_handler(nxt_unit_request_info_t *req)
623{
576 PyObject *msg, *future, *res;
577 nxt_py_asgi_http_t *http;
578
579 http = req->data;
580
581 nxt_unit_req_debug(req, "asgi_http_close_handler");
582
583 http->closed = 1;
584
624 nxt_py_asgi_http_t *http;
625
626 http = req->data;
627
628 nxt_unit_req_debug(req, "asgi_http_close_handler");
629
630 http->closed = 1;
631
585 if (http->receive_future == NULL) {
586 return;
587 }
588
589 msg = nxt_py_asgi_new_msg(req, nxt_py_http_disconnect_str);
590 if (nxt_slow_path(msg == NULL)) {
591 return;
592 }
593
594 if (msg == Py_None) {
595 Py_DECREF(msg);
596 return;
597 }
598
599 future = http->receive_future;
600 http->receive_future = NULL;
601
602 res = PyObject_CallMethodObjArgs(future, nxt_py_set_result_str, msg, NULL);
603 if (nxt_slow_path(res == NULL)) {
604 nxt_unit_req_alert(req, "'set_result' call failed");
605 nxt_python_print_exception();
606 }
607
608 Py_XDECREF(res);
609 Py_DECREF(future);
610
611 Py_DECREF(msg);
632 nxt_py_asgi_http_emit_disconnect(http);
612}
613
614
615static PyObject *
616nxt_py_asgi_http_done(PyObject *self, PyObject *future)
617{
618 int rc;
619 PyObject *res;

--- 31 unchanged lines hidden ---
633}
634
635
636static PyObject *
637nxt_py_asgi_http_done(PyObject *self, PyObject *future)
638{
639 int rc;
640 PyObject *res;

--- 31 unchanged lines hidden ---