expose http_file interface to python.

This commit is contained in:
Joris Vink 2017-02-01 21:23:56 +01:00
parent 0250c8ecba
commit 6578fc6589
2 changed files with 148 additions and 0 deletions

View File

@ -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

View File

@ -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
@ -633,6 +641,20 @@ pyhttp_request_alloc(struct http_request *req)
return ((PyObject *)pyreq);
}
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)
{
@ -739,6 +761,13 @@ pyhttp_populate_post(struct pyhttp_request *pyreq, PyObject *args)
Py_RETURN_TRUE;
}
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)
{
@ -761,6 +790,66 @@ pyhttp_argument(struct pyhttp_request *pyreq, PyObject *args)
return (value);
}
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)
{
@ -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