Python HTTP improvements.

1) Add @kore.prerequest python decorator.

Using this decorator on a function will cause that function
to always be executed *before* any page handler is run.

eg:

@kore.prerequest
def _check(req):
    if req.method == kore.HTTP_METHOD_POST:
        req.populate_post()

2) Allow attributes to be set on the pyhttp object.
This commit is contained in:
Joris Vink 2019-06-05 23:45:45 +02:00
parent 89e58fa474
commit 9cc58d45c1
2 changed files with 58 additions and 1 deletions

View File

@ -45,6 +45,7 @@ static PyObject *python_kore_fatalx(PyObject *, PyObject *);
static PyObject *python_kore_suspend(PyObject *, PyObject *);
static PyObject *python_kore_shutdown(PyObject *, PyObject *);
static PyObject *python_kore_bind_unix(PyObject *, PyObject *);
static PyObject *python_kore_prerequest(PyObject *, PyObject *);
static PyObject *python_kore_task_create(PyObject *, PyObject *);
static PyObject *python_kore_socket_wrap(PyObject *, PyObject *);
static PyObject *python_kore_gather(PyObject *, PyObject *, PyObject *);
@ -80,6 +81,7 @@ static struct PyMethodDef pykore_methods[] = {
METHOD("suspend", python_kore_suspend, METH_VARARGS),
METHOD("shutdown", python_kore_shutdown, METH_NOARGS),
METHOD("bind_unix", python_kore_bind_unix, METH_VARARGS),
METHOD("prerequest", python_kore_prerequest, METH_VARARGS),
METHOD("task_create", python_kore_task_create, METH_VARARGS),
METHOD("socket_wrap", python_kore_socket_wrap, METH_VARARGS),
METHOD("websocket_broadcast", python_websocket_broadcast, METH_VARARGS),
@ -544,6 +546,7 @@ static PyTypeObject pyconnection_type = {
struct pyhttp_request {
PyObject_HEAD
struct http_request *req;
PyObject *dict;
PyObject *data;
};
@ -621,10 +624,13 @@ static PyTypeObject pyhttp_request_type = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "kore.http_request",
.tp_doc = "struct http_request",
.tp_setattro = PyObject_GenericSetAttr,
.tp_getattro = PyObject_GenericGetAttr,
.tp_getset = pyhttp_request_getset,
.tp_methods = pyhttp_request_methods,
.tp_dealloc = (destructor)pyhttp_dealloc,
.tp_basicsize = sizeof(struct pyhttp_request),
.tp_dictoffset = offsetof(struct pyhttp_request, dict),
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
};

View File

@ -40,6 +40,13 @@
#include "python_api.h"
#include "python_methods.h"
struct reqcall {
PyObject *f;
LIST_ENTRY(reqcall) list;
};
LIST_HEAD(reqcall_list, reqcall);
static PyMODINIT_FUNC python_module_init(void);
static PyObject *python_import(const char *);
static PyObject *pyconnection_alloc(struct connection *);
@ -177,6 +184,7 @@ static PyMemAllocatorEx allocator = {
};
static TAILQ_HEAD(, pyproc) procs;
static struct reqcall_list prereq;
static struct kore_pool coro_pool;
static struct kore_pool iterobj_pool;
@ -204,6 +212,8 @@ kore_python_init(void)
coro_id = 0;
coro_count = 0;
LIST_INIT(&prereq);
TAILQ_INIT(&procs);
TAILQ_INIT(&coro_runnable);
TAILQ_INIT(&coro_suspended);
@ -620,6 +630,7 @@ pyconnection_dealloc(struct pyconnection *pyc)
static void
pyhttp_dealloc(struct pyhttp_request *pyreq)
{
Py_XDECREF(pyreq->dict);
Py_XDECREF(pyreq->data);
PyObject_Del((PyObject *)pyreq);
}
@ -633,7 +644,8 @@ pyhttp_file_dealloc(struct pyhttp_file *pyfile)
static int
python_runtime_http_request(void *addr, struct http_request *req)
{
PyObject *pyret, *pyreq, *args, *callable;
struct reqcall *rq;
PyObject *pyret, *pyreq, *args, *callable;
if (req->py_coro != NULL) {
python_coro_wakeup(req->py_coro);
@ -650,6 +662,26 @@ python_runtime_http_request(void *addr, struct http_request *req)
if ((pyreq = pyhttp_request_alloc(req)) == NULL)
fatal("python_runtime_http_request: pyreq alloc failed");
LIST_FOREACH(rq, &prereq, list) {
PyErr_Clear();
pyret = PyObject_CallFunctionObjArgs(rq->f, pyreq, NULL);
if (pyret == NULL) {
Py_DECREF(pyreq);
kore_python_log_error("prerequest");
http_response(req, HTTP_STATUS_INTERNAL_ERROR, NULL, 0);
return (KORE_RESULT_OK);
}
if (pyret == Py_False) {
Py_DECREF(pyreq);
Py_DECREF(pyret);
return (KORE_RESULT_OK);
}
Py_DECREF(pyret);
}
if ((args = PyTuple_New(1)) == NULL)
fatal("python_runtime_http_request: PyTuple_New failed");
@ -1103,6 +1135,24 @@ python_kore_bind_unix(PyObject *self, PyObject *args)
Py_RETURN_TRUE;
}
static PyObject *
python_kore_prerequest(PyObject *self, PyObject *args)
{
PyObject *f;
struct reqcall *rq;
if (!PyArg_ParseTuple(args, "O", &f))
return (NULL);
rq = kore_calloc(1, sizeof(*rq));
rq->f = f;
Py_INCREF(f);
LIST_INSERT_HEAD(&prereq, rq, list);
return (f);
}
static PyObject *
python_kore_task_create(PyObject *self, PyObject *args)
{
@ -3110,6 +3160,7 @@ pyhttp_request_alloc(const struct http_request *req)
ptr.cp = req;
pyreq->req = ptr.p;
pyreq->data = NULL;
pyreq->dict = NULL;
return ((PyObject *)pyreq);
}