mirror of
https://github.com/jamesroberts/fastwsgi.git
synced 2025-12-19 05:09:38 -06:00
Added type finalize and destructor into start_response (#40)
This commit is contained in:
@@ -93,12 +93,7 @@ int reset_wsgi_input(client_t * client)
|
||||
|
||||
void free_start_response(client_t * client)
|
||||
{
|
||||
if (client->start_response) {
|
||||
Py_CLEAR(client->start_response->headers);
|
||||
Py_CLEAR(client->start_response->status);
|
||||
Py_CLEAR(client->start_response->exc_info);
|
||||
Py_CLEAR(client->start_response);
|
||||
}
|
||||
Py_CLEAR(client->start_response);
|
||||
}
|
||||
|
||||
void reset_response_preload(client_t * client)
|
||||
|
||||
@@ -623,6 +623,7 @@ int init_srv()
|
||||
configure_parser_settings(&g_srv.parser_settings);
|
||||
init_constants();
|
||||
init_request_dict();
|
||||
PyType_Ready(&StartResponse_Type);
|
||||
|
||||
sockaddr_t addr;
|
||||
int tcp_flags = 0;
|
||||
|
||||
@@ -1,94 +1,104 @@
|
||||
#include <stdbool.h>
|
||||
#include "start_response.h"
|
||||
|
||||
void set_status_error() {
|
||||
char* err_msg = "'status' must be a 3-digit string";
|
||||
void set_status_error()
|
||||
{
|
||||
const char * err_msg = "'status' must be a 3-digit string";
|
||||
PyErr_SetString(PyExc_ValueError, err_msg);
|
||||
}
|
||||
|
||||
void set_header_tuple_error() {
|
||||
char* err_msg = "start_response argument 2 expects a list of 2-tuples (str, str)";
|
||||
void set_header_tuple_error()
|
||||
{
|
||||
const char * err_msg = "start_response: argument 2 expects a list of 2-tuples (str, str)";
|
||||
PyErr_SetString(PyExc_TypeError, err_msg);
|
||||
}
|
||||
|
||||
void set_header_list_error(PyObject* headers) {
|
||||
PyErr_Format(
|
||||
PyExc_TypeError,
|
||||
"start_response argument 2 expects a list of 2-tuples, got '%s' instead.",
|
||||
Py_TYPE(headers)->tp_name
|
||||
);
|
||||
void set_header_list_error(PyObject * headers)
|
||||
{
|
||||
const char * err_msg = "start_response: argument 2 expects a list of 2-tuples, got '%s' instead.";
|
||||
PyErr_Format(PyExc_TypeError, err_msg, Py_TYPE(headers)->tp_name);
|
||||
}
|
||||
|
||||
void set_exc_info_type_error(PyObject* exc_info) {
|
||||
PyErr_Format(
|
||||
PyExc_TypeError,
|
||||
"start_response argument 3 expects a 3-tuple, got '%s' instead.",
|
||||
Py_TYPE(exc_info)->tp_name
|
||||
);
|
||||
void set_exc_info_type_error(PyObject * exc_info)
|
||||
{
|
||||
const char * err_msg = "start_response: argument 3 expects a 3-tuple, got '%s' instead.";
|
||||
PyErr_Format(PyExc_TypeError, err_msg, Py_TYPE(exc_info)->tp_name);
|
||||
}
|
||||
|
||||
void set_exc_info_missing_error() {
|
||||
void set_exc_info_missing_error()
|
||||
{
|
||||
char* err_msg = "'exc_info' is required in the second call of 'start_response'";
|
||||
PyErr_SetString(PyExc_TypeError, err_msg);
|
||||
}
|
||||
|
||||
bool is_valid_status(PyObject* status) {
|
||||
bool valid = PyUnicode_Check(status) && PyUnicode_GET_LENGTH(status) >= 3;
|
||||
if (!valid) set_status_error();
|
||||
return valid;
|
||||
static
|
||||
bool is_valid_status(PyObject * status)
|
||||
{
|
||||
if (PyUnicode_Check(status))
|
||||
if (PyUnicode_GET_LENGTH(status) >= 3)
|
||||
return true;
|
||||
|
||||
set_status_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_valid_header_tuple(PyObject* tuple) {
|
||||
bool valid = false;
|
||||
static
|
||||
bool is_valid_header_tuple(PyObject * tuple)
|
||||
{
|
||||
if (PyTuple_Check(tuple))
|
||||
if (PyTuple_GET_SIZE(tuple) == 2)
|
||||
if (PyUnicode_Check(PyTuple_GET_ITEM(tuple, 0)))
|
||||
if (PyUnicode_Check(PyTuple_GET_ITEM(tuple, 1)))
|
||||
return true;
|
||||
|
||||
if (PyTuple_Check(tuple) && PyTuple_GET_SIZE(tuple) == 2) {
|
||||
int field = PyUnicode_Check(PyTuple_GET_ITEM(tuple, 0));
|
||||
int value = PyUnicode_Check(PyTuple_GET_ITEM(tuple, 1));
|
||||
valid = field && value;
|
||||
}
|
||||
if (!valid) set_header_tuple_error();
|
||||
return valid;
|
||||
set_header_tuple_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_valid_headers(PyObject* headers) {
|
||||
bool valid = PyList_Check(headers);
|
||||
|
||||
if (!valid) {
|
||||
set_header_list_error(headers);
|
||||
return valid;
|
||||
static
|
||||
bool is_valid_headers(PyObject * headers)
|
||||
{
|
||||
if (PyList_Check(headers)) {
|
||||
Py_ssize_t len = PyList_GET_SIZE(headers);
|
||||
for (Py_ssize_t i = 0; i < len; i++) {
|
||||
if (!is_valid_header_tuple(PyList_GET_ITEM(headers, i)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
for (Py_ssize_t i = 0; i < PyList_GET_SIZE(headers); i++) {
|
||||
valid = is_valid_header_tuple(PyList_GET_ITEM(headers, i));
|
||||
if (!valid) break;
|
||||
}
|
||||
return valid;
|
||||
set_header_list_error(headers);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_valid_exc_info(StartResponse* sr) {
|
||||
bool valid = true;
|
||||
|
||||
static
|
||||
bool is_valid_exc_info(StartResponse * sr)
|
||||
{
|
||||
if (sr->exc_info && sr->exc_info != Py_None) {
|
||||
valid = PyTuple_Check(sr->exc_info) && PyTuple_GET_SIZE(sr->exc_info);
|
||||
if (!valid) set_exc_info_type_error(sr->exc_info);
|
||||
if (PyTuple_Check(sr->exc_info))
|
||||
if (PyTuple_GET_SIZE(sr->exc_info) == 3)
|
||||
return true;
|
||||
|
||||
set_exc_info_type_error(sr->exc_info);
|
||||
return false;
|
||||
}
|
||||
else if (sr->called == 1) {
|
||||
if (sr->called == 1) {
|
||||
set_exc_info_missing_error();
|
||||
valid = false;
|
||||
return false;
|
||||
}
|
||||
return valid;
|
||||
return true;
|
||||
}
|
||||
|
||||
PyObject* start_response_call(PyObject* self, PyObject* args, PyObject* kwargs) {
|
||||
StartResponse* sr = (StartResponse*)self;
|
||||
|
||||
static
|
||||
PyObject * start_response_call(StartResponse * sr, PyObject * args, PyObject * kwargs)
|
||||
{
|
||||
if (sr->called == 1) {
|
||||
Py_CLEAR(sr->status);
|
||||
Py_CLEAR(sr->headers);
|
||||
}
|
||||
|
||||
sr->exc_info = NULL;
|
||||
if (!PyArg_UnpackTuple(args, "start_response", 2, 3, &sr->status, &sr->headers, &sr->exc_info))
|
||||
|
||||
int rc = PyArg_UnpackTuple(args, "start_response", 2, 3, &sr->status, &sr->headers, &sr->exc_info);
|
||||
if (rc == (int)false)
|
||||
return NULL;
|
||||
|
||||
if (!is_valid_status(sr->status))
|
||||
@@ -109,12 +119,22 @@ PyObject* start_response_call(PyObject* self, PyObject* args, PyObject* kwargs)
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static
|
||||
void start_response_dealloc(StartResponse * self)
|
||||
{
|
||||
Py_CLEAR(self->status);
|
||||
Py_CLEAR(self->headers);
|
||||
Py_CLEAR(self->exc_info);
|
||||
PyObject_Del(self);
|
||||
}
|
||||
|
||||
PyTypeObject StartResponse_Type = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"start_response",
|
||||
sizeof(StartResponse),
|
||||
0,
|
||||
(destructor)PyObject_FREE,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
start_response_call
|
||||
.tp_name = "start_response",
|
||||
.tp_basicsize = sizeof(StartResponse),
|
||||
.tp_itemsize = 0,
|
||||
.tp_dealloc = (destructor) start_response_dealloc,
|
||||
.tp_call = (ternaryfunc) start_response_call,
|
||||
.tp_flags = Py_TPFLAGS_DEFAULT,
|
||||
.tp_finalize = NULL
|
||||
};
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
#include "common.h"
|
||||
|
||||
typedef struct {
|
||||
PyObject ob_base;
|
||||
PyObject* status;
|
||||
PyObject* headers;
|
||||
PyObject* exc_info;
|
||||
int called;
|
||||
PyObject ob_base;
|
||||
PyObject * status;
|
||||
PyObject * headers;
|
||||
PyObject * exc_info;
|
||||
int called;
|
||||
} StartResponse;
|
||||
|
||||
extern PyTypeObject StartResponse_Type;
|
||||
@@ -16,12 +16,14 @@ extern PyTypeObject StartResponse_Type;
|
||||
INLINE
|
||||
static StartResponse * create_start_response(void)
|
||||
{
|
||||
StartResponse * response = PyObject_NEW(StartResponse, &StartResponse_Type);
|
||||
response->status = NULL;
|
||||
response->headers = NULL;
|
||||
response->exc_info = NULL;
|
||||
response->called = 0;
|
||||
return response;
|
||||
StartResponse * sr = PyObject_NEW(StartResponse, &StartResponse_Type);
|
||||
if (sr) {
|
||||
sr->status = NULL;
|
||||
sr->headers = NULL;
|
||||
sr->exc_info = NULL;
|
||||
sr->called = 0;
|
||||
}
|
||||
return sr;
|
||||
}
|
||||
|
||||
void set_status_error();
|
||||
|
||||
Reference in New Issue
Block a user