commit 6578fc65894026cb3fdbb49adf7f4a3f225c2aae
parent 0250c8ecba08681b98839d5f00defa3b25d153aa
Author: Joris Vink <joris@coders.se>
Date: Wed, 1 Feb 2017 21:23:56 +0100
expose http_file interface to python.
Diffstat:
2 files changed, 148 insertions(+), 0 deletions(-)
diff --git a/includes/python_methods.h b/includes/python_methods.h
@@ -70,13 +70,21 @@ struct pyhttp_request {
struct http_request *req;
};
+struct pyhttp_file {
+ PyObject_HEAD
+ struct http_file *file;
+};
+
static void pyhttp_dealloc(struct pyhttp_request *);
+static void pyhttp_file_dealloc(struct pyhttp_file *);
static PyObject *pyhttp_response(struct pyhttp_request *, PyObject *);
static PyObject *pyhttp_argument(struct pyhttp_request *, PyObject *);
static PyObject *pyhttp_body_read(struct pyhttp_request *, PyObject *);
+static PyObject *pyhttp_file_lookup(struct pyhttp_request *, PyObject *);
static PyObject *pyhttp_populate_get(struct pyhttp_request *, PyObject *);
static PyObject *pyhttp_populate_post(struct pyhttp_request *, PyObject *);
+static PyObject *pyhttp_populate_multi(struct pyhttp_request *, PyObject *);
static PyObject *pyhttp_request_header(struct pyhttp_request *, PyObject *);
static PyObject *pyhttp_response_header(struct pyhttp_request *, PyObject *);
static PyObject *pyhttp_websocket_handshake(struct pyhttp_request *,
@@ -86,8 +94,10 @@ static PyMethodDef pyhttp_request_methods[] = {
METHOD("response", pyhttp_response, METH_VARARGS),
METHOD("argument", pyhttp_argument, METH_VARARGS),
METHOD("body_read", pyhttp_body_read, METH_VARARGS),
+ METHOD("file_lookup", pyhttp_file_lookup, METH_VARARGS),
METHOD("populate_get", pyhttp_populate_get, METH_NOARGS),
METHOD("populate_post", pyhttp_populate_post, METH_NOARGS),
+ METHOD("populate_multi", pyhttp_populate_multi, METH_NOARGS),
METHOD("request_header", pyhttp_request_header, METH_VARARGS),
METHOD("response_header", pyhttp_response_header, METH_VARARGS),
METHOD("websocket_handshake", pyhttp_websocket_handshake, METH_VARARGS),
@@ -125,4 +135,31 @@ static PyTypeObject pyhttp_request_type = {
.tp_basicsize = sizeof(struct pyhttp_request),
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
};
+
+static PyObject *pyhttp_file_read(struct pyhttp_file *, PyObject *);
+
+static PyMethodDef pyhttp_file_methods[] = {
+ METHOD("read", pyhttp_file_read, METH_VARARGS),
+ METHOD(NULL, NULL, -1)
+};
+
+static PyObject *pyhttp_file_get_name(struct pyhttp_file *, void *);
+static PyObject *pyhttp_file_get_filename(struct pyhttp_file *, void *);
+
+static PyGetSetDef pyhttp_file_getset[] = {
+ GETTER("name", pyhttp_file_get_name),
+ GETTER("filename", pyhttp_file_get_filename),
+ GETTER(NULL, NULL)
+};
+
+static PyTypeObject pyhttp_file_type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = "kore.http_file",
+ .tp_doc = "struct http_file",
+ .tp_getset = pyhttp_file_getset,
+ .tp_methods = pyhttp_file_methods,
+ .tp_dealloc = (destructor)pyhttp_file_dealloc,
+ .tp_basicsize = sizeof(struct pyhttp_file),
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+};
#endif
diff --git a/src/python.c b/src/python.c
@@ -35,6 +35,7 @@ static PyObject *pyconnection_alloc(struct connection *);
static PyObject *python_callable(PyObject *, const char *);
#if !defined(KORE_NO_HTTP)
+static PyObject *pyhttp_file_alloc(struct http_file *);
static PyObject *pyhttp_request_alloc(struct http_request *);
#endif
@@ -247,6 +248,12 @@ pyhttp_dealloc(struct pyhttp_request *pyreq)
PyObject_Del((PyObject *)pyreq);
}
+static void
+pyhttp_file_dealloc(struct pyhttp_file *pyfile)
+{
+ PyObject_Del((PyObject *)pyfile);
+}
+
static int
python_runtime_http_request(void *addr, struct http_request *req)
{
@@ -469,6 +476,7 @@ python_module_init(void)
}
#if !defined(KORE_NO_HTTP)
+ python_push_type("pyhttp_file", pykore, &pyhttp_file_type);
python_push_type("pyhttp_request", pykore, &pyhttp_request_type);
#endif
@@ -634,6 +642,20 @@ pyhttp_request_alloc(struct http_request *req)
}
static PyObject *
+pyhttp_file_alloc(struct http_file *file)
+{
+ struct pyhttp_file *pyfile;
+
+ pyfile = PyObject_New(struct pyhttp_file, &pyhttp_file_type);
+ if (pyfile == NULL)
+ return (NULL);
+
+ pyfile->file = file;
+
+ return ((PyObject *)pyfile);
+}
+
+static PyObject *
pyhttp_response(struct pyhttp_request *pyreq, PyObject *args)
{
Py_buffer body;
@@ -740,6 +762,13 @@ pyhttp_populate_post(struct pyhttp_request *pyreq, PyObject *args)
}
static PyObject *
+pyhttp_populate_multi(struct pyhttp_request *pyreq, PyObject *args)
+{
+ http_populate_multipart_form(pyreq->req);
+ Py_RETURN_TRUE;
+}
+
+static PyObject *
pyhttp_argument(struct pyhttp_request *pyreq, PyObject *args)
{
const char *name;
@@ -762,6 +791,66 @@ pyhttp_argument(struct pyhttp_request *pyreq, PyObject *args)
}
static PyObject *
+pyhttp_file_lookup(struct pyhttp_request *pyreq, PyObject *args)
+{
+ const char *name;
+ struct http_file *file;
+ PyObject *pyfile;
+
+ if (!PyArg_ParseTuple(args, "s", &name)) {
+ PyErr_SetString(PyExc_TypeError, "invalid parameters");
+ return (NULL);
+ }
+
+ if ((file = http_file_lookup(pyreq->req, name)) == NULL) {
+ Py_RETURN_NONE;
+ }
+
+ if ((pyfile = pyhttp_file_alloc(file)) == NULL)
+ return (PyErr_NoMemory());
+
+ return (pyfile);
+}
+
+static PyObject *
+pyhttp_file_read(struct pyhttp_file *pyfile, PyObject *args)
+{
+ ssize_t ret;
+ size_t len;
+ Py_ssize_t pylen;
+ PyObject *result;
+ u_int8_t buf[1024];
+
+ if (!PyArg_ParseTuple(args, "n", &pylen) || pylen < 0) {
+ PyErr_SetString(PyExc_TypeError, "invalid parameters");
+ return (NULL);
+ }
+
+ len = (size_t)pylen;
+ if (len > sizeof(buf)) {
+ PyErr_SetString(PyExc_RuntimeError, "len > sizeof(buf)");
+ return (NULL);
+ }
+
+ ret = http_file_read(pyfile->file, buf, len);
+ if (ret == -1) {
+ PyErr_SetString(PyExc_RuntimeError, "http_file_read() failed");
+ return (NULL);
+ }
+
+ if (ret > INT_MAX) {
+ PyErr_SetString(PyExc_RuntimeError, "ret > INT_MAX");
+ return (NULL);
+ }
+
+ result = Py_BuildValue("ny#", ret, buf, (int)ret);
+ if (result == NULL)
+ return (PyErr_NoMemory());
+
+ return (result);
+}
+
+static PyObject *
pyhttp_websocket_handshake(struct pyhttp_request *pyreq, PyObject *args)
{
const char *onconnect, *onmsg, *ondisconnect;
@@ -947,4 +1036,26 @@ pyhttp_get_connection(struct pyhttp_request *pyreq, void *closure)
return (pyc);
}
+
+static PyObject *
+pyhttp_file_get_name(struct pyhttp_file *pyfile, void *closure)
+{
+ PyObject *name;
+
+ if ((name = PyUnicode_FromString(pyfile->file->name)) == NULL)
+ return (PyErr_NoMemory());
+
+ return (name);
+}
+
+static PyObject *
+pyhttp_file_get_filename(struct pyhttp_file *pyfile, void *closure)
+{
+ PyObject *name;
+
+ if ((name = PyUnicode_FromString(pyfile->file->filename)) == NULL)
+ return (PyErr_NoMemory());
+
+ return (name);
+}
#endif