mirror of
https://github.com/jorisvink/kore
synced 2025-03-09 12:39:01 -04:00
Python: allow route hooks via kore.route().
Adding the hooks keyword with a dictionary attached to specify the relevant hooks will hook them for the given route. Eg: domain.route("/", self.index, methods=["get"], hooks={ "on_free": self.request_free } ) These are the same hooks available via a normal Kore route configuration.
This commit is contained in:
parent
97ef486d22
commit
e8e01980fc
@ -44,7 +44,7 @@ state_setup(struct http_request *req)
|
||||
{
|
||||
struct kore_curl *client;
|
||||
|
||||
client = http_state_create(req, sizeof(*client), NULL);
|
||||
client = http_state_create(req, sizeof(*client));
|
||||
|
||||
if (!kore_curl_init(client,
|
||||
"http://ftp.eu.openbsd.org/pub/OpenBSD/README", KORE_CURL_ASYNC)) {
|
||||
|
@ -59,7 +59,7 @@ state_setup(struct http_request *req)
|
||||
{
|
||||
struct kore_curl *client;
|
||||
|
||||
client = http_state_create(req, sizeof(*client), NULL);
|
||||
client = http_state_create(req, sizeof(*client));
|
||||
|
||||
/* Initialize curl. */
|
||||
if (!kore_curl_init(client, "https://kore.io", KORE_CURL_ASYNC)) {
|
||||
|
@ -85,7 +85,7 @@ request_perform_init(struct http_request *req)
|
||||
|
||||
/* Setup our state context (if not yet set). */
|
||||
if (!http_state_exists(req)) {
|
||||
state = http_state_create(req, sizeof(*state), NULL);
|
||||
state = http_state_create(req, sizeof(*state));
|
||||
|
||||
/*
|
||||
* Initialize the kore_pgsql data structure and bind it
|
||||
|
@ -413,8 +413,7 @@ const char *http_media_type(const char *);
|
||||
void *http_state_get(struct http_request *);
|
||||
int http_state_exists(struct http_request *);
|
||||
void http_state_cleanup(struct http_request *);
|
||||
void *http_state_create(struct http_request *, size_t,
|
||||
void (*onfree)(struct http_request *));
|
||||
void *http_state_create(struct http_request *, size_t);
|
||||
|
||||
int http_argument_urldecode(char *);
|
||||
int http_header_recv(struct netbuf *);
|
||||
|
@ -287,6 +287,7 @@ struct kore_runtime {
|
||||
int type;
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
int (*http_request)(void *, struct http_request *);
|
||||
void (*http_request_free)(void *, struct http_request *);
|
||||
void (*http_body_chunk)(void *,
|
||||
struct http_request *, const void *, size_t);
|
||||
int (*validator)(void *, struct http_request *, const void *);
|
||||
@ -327,6 +328,7 @@ struct kore_route {
|
||||
struct kore_domain *dom;
|
||||
struct kore_auth *auth;
|
||||
struct kore_runtime_call *rcall;
|
||||
struct kore_runtime_call *on_free;
|
||||
struct kore_runtime_call *on_headers;
|
||||
struct kore_runtime_call *on_body_chunk;
|
||||
|
||||
@ -993,6 +995,8 @@ void kore_runtime_connect(struct kore_runtime_call *, struct connection *);
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
int kore_runtime_http_request(struct kore_runtime_call *,
|
||||
struct http_request *);
|
||||
void kore_runtime_http_request_free(struct kore_runtime_call *,
|
||||
struct http_request *);
|
||||
void kore_runtime_http_body_chunk(struct kore_runtime_call *,
|
||||
struct http_request *, const void *, size_t);
|
||||
int kore_runtime_validator(struct kore_runtime_call *,
|
||||
|
20
src/config.c
20
src/config.c
@ -111,6 +111,7 @@ static int configure_client_verify_depth(char *);
|
||||
static int configure_route(char *);
|
||||
static int configure_route_methods(char *);
|
||||
static int configure_route_handler(char *);
|
||||
static int configure_route_on_free(char *);
|
||||
static int configure_route_on_headers(char *);
|
||||
static int configure_route_on_body_chunk(char *);
|
||||
static int configure_filemap(char *);
|
||||
@ -201,6 +202,7 @@ static struct {
|
||||
{ "handler", configure_route_handler },
|
||||
{ "on_headers", configure_route_on_headers },
|
||||
{ "on_body_chunk", configure_route_on_body_chunk },
|
||||
{ "on_free", configure_route_on_free },
|
||||
{ "methods", configure_route_methods },
|
||||
{ "filemap", configure_filemap },
|
||||
{ "redirect", configure_redirect },
|
||||
@ -1203,6 +1205,24 @@ configure_route_on_body_chunk(char *name)
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
configure_route_on_free(char *name)
|
||||
{
|
||||
if (current_route == NULL) {
|
||||
kore_log(LOG_ERR,
|
||||
"on_free keyword not inside of route context");
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
if ((current_route->on_free = kore_runtime_getcall(name)) == NULL) {
|
||||
kore_log(LOG_ERR, "on_free callback '%s' for '%s' not found",
|
||||
name, current_route->path);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
configure_route_methods(char *options)
|
||||
{
|
||||
|
@ -442,8 +442,8 @@ http_request_free(struct http_request *req)
|
||||
struct http_header *hdr, *next;
|
||||
struct http_cookie *ck, *cknext;
|
||||
|
||||
if (req->onfree != NULL)
|
||||
req->onfree(req);
|
||||
if (req->rt->on_free != NULL)
|
||||
kore_runtime_http_request_free(req->rt->on_free, req);
|
||||
|
||||
if (req->runlock != NULL) {
|
||||
LIST_REMOVE(req->runlock, list);
|
||||
@ -1454,14 +1454,12 @@ http_state_exists(struct http_request *req)
|
||||
}
|
||||
|
||||
void *
|
||||
http_state_create(struct http_request *req, size_t len,
|
||||
void (*onfree)(struct http_request *))
|
||||
http_state_create(struct http_request *req, size_t len)
|
||||
{
|
||||
if (req->hdlr_extra != NULL)
|
||||
fatal("http_state_create: state already exists");
|
||||
|
||||
req->state_len = len;
|
||||
req->onfree = onfree;
|
||||
req->hdlr_extra = kore_calloc(1, len);
|
||||
|
||||
return (req->hdlr_extra);
|
||||
@ -2035,7 +2033,6 @@ http_request_new(struct connection *c, const char *host,
|
||||
req->status = 0;
|
||||
req->method = m;
|
||||
req->agent = NULL;
|
||||
req->onfree = NULL;
|
||||
req->referer = NULL;
|
||||
req->runlock = NULL;
|
||||
req->flags = flags;
|
||||
|
104
src/python.c
104
src/python.c
@ -88,6 +88,9 @@ static int python_route_params(PyObject *, struct kore_route *,
|
||||
static int python_route_methods(PyObject *, PyObject *,
|
||||
struct kore_route *);
|
||||
static int python_route_auth(PyObject *, struct kore_route *);
|
||||
static int python_route_hooks(PyObject *, struct kore_route *);
|
||||
static int python_route_hook_set(PyObject *, const char *,
|
||||
struct kore_runtime_call **);
|
||||
|
||||
static int python_coro_run(struct python_coro *);
|
||||
static void python_coro_wakeup(struct python_coro *);
|
||||
@ -146,6 +149,9 @@ static void python_push_type(const char *, PyObject *, PyTypeObject *);
|
||||
|
||||
static int python_validator_check(PyObject *);
|
||||
static int python_runtime_http_request(void *, struct http_request *);
|
||||
static void python_runtime_http_request_free(void *, struct http_request *);
|
||||
static void python_runtime_http_body_chunk(void *, struct http_request *,
|
||||
const void *, size_t);
|
||||
static int python_runtime_validator(void *, struct http_request *,
|
||||
const void *);
|
||||
static void python_runtime_wsmessage(void *, struct connection *,
|
||||
@ -175,6 +181,8 @@ struct kore_module_functions kore_python_module = {
|
||||
struct kore_runtime kore_python_runtime = {
|
||||
KORE_RUNTIME_PYTHON,
|
||||
.http_request = python_runtime_http_request,
|
||||
.http_body_chunk = python_runtime_http_body_chunk,
|
||||
.http_request_free = python_runtime_http_request_free,
|
||||
.validator = python_runtime_validator,
|
||||
.wsconnect = python_runtime_connect,
|
||||
.wsmessage = python_runtime_wsmessage,
|
||||
@ -1318,6 +1326,49 @@ python_runtime_http_request(void *addr, struct http_request *req)
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
static void
|
||||
python_runtime_http_request_free(void *addr, struct http_request *req)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (req->py_req == NULL)
|
||||
fatal("%s: py_req is NULL", __func__);
|
||||
|
||||
PyErr_Clear();
|
||||
ret = PyObject_CallFunctionObjArgs(addr, req->py_req, NULL);
|
||||
|
||||
if (ret == NULL)
|
||||
kore_python_log_error("python_runtime_http_request_free");
|
||||
|
||||
Py_XDECREF(ret);
|
||||
}
|
||||
|
||||
static void
|
||||
python_runtime_http_body_chunk(void *addr, struct http_request *req,
|
||||
const void *data, size_t len)
|
||||
{
|
||||
PyObject *args, *ret;
|
||||
|
||||
if (req->py_req == NULL) {
|
||||
if ((req->py_req = pyhttp_request_alloc(req)) == NULL)
|
||||
fatal("%s: pyreq alloc failed", __func__);
|
||||
}
|
||||
|
||||
if ((args = Py_BuildValue("(Oy#)", req->py_req, data, len)) == NULL) {
|
||||
kore_python_log_error("python_runtime_http_body_chunk");
|
||||
return;
|
||||
}
|
||||
|
||||
PyErr_Clear();
|
||||
ret = PyObject_Call(addr, args, NULL);
|
||||
|
||||
if (ret == NULL)
|
||||
kore_python_log_error("python_runtime_http_body_chunk");
|
||||
|
||||
Py_XDECREF(ret);
|
||||
Py_DECREF(args);
|
||||
}
|
||||
|
||||
static int
|
||||
python_runtime_validator(void *addr, struct http_request *req, const void *data)
|
||||
{
|
||||
@ -5358,6 +5409,14 @@ python_route_install(struct pyroute *route)
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if ((obj = PyDict_GetItemString(kwargs, "hooks")) != NULL) {
|
||||
if (!python_route_hooks(obj, rt)) {
|
||||
kore_python_log_error("python_route_install");
|
||||
kore_route_free(rt);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rt->path[0] == '/') {
|
||||
@ -5605,6 +5664,51 @@ python_route_auth(PyObject *dict, struct kore_route *rt)
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
python_route_hooks(PyObject *dict, struct kore_route *rt)
|
||||
{
|
||||
if (!PyDict_CheckExact(dict))
|
||||
return (KORE_RESULT_ERROR);
|
||||
|
||||
if (!python_route_hook_set(dict, "on_free", &rt->on_free))
|
||||
return (KORE_RESULT_ERROR);
|
||||
|
||||
if (!python_route_hook_set(dict, "on_headers", &rt->on_headers))
|
||||
return (KORE_RESULT_ERROR);
|
||||
|
||||
if (!python_route_hook_set(dict, "on_body_chunk", &rt->on_body_chunk))
|
||||
return (KORE_RESULT_ERROR);
|
||||
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
python_route_hook_set(PyObject *dict, const char *name,
|
||||
struct kore_runtime_call **out)
|
||||
{
|
||||
PyObject *obj;
|
||||
struct kore_runtime_call *rcall;
|
||||
|
||||
if ((obj = PyDict_GetItemString(dict, name)) == NULL)
|
||||
return (KORE_RESULT_OK);
|
||||
|
||||
if (!PyCallable_Check(obj)) {
|
||||
PyErr_Format(PyExc_RuntimeError,
|
||||
"%s for a route not callable", name);
|
||||
Py_DECREF(obj);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
rcall = kore_calloc(1, sizeof(struct kore_runtime_call));
|
||||
rcall->addr = obj;
|
||||
rcall->runtime = &kore_python_runtime;
|
||||
|
||||
Py_INCREF(rcall->addr);
|
||||
*out = rcall;
|
||||
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
#if defined(KORE_USE_PGSQL)
|
||||
static PyObject *
|
||||
python_kore_pgsql_query(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||
|
@ -33,6 +33,7 @@ static void native_runtime_connect(void *, struct connection *);
|
||||
static void native_runtime_configure(void *, int, char **);
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
static int native_runtime_http_request(void *, struct http_request *);
|
||||
static void native_runtime_http_request_free(void *, struct http_request *);
|
||||
static void native_runtime_http_body_chunk(void *, struct http_request *,
|
||||
const void *, size_t);
|
||||
static int native_runtime_validator(void *, struct http_request *,
|
||||
@ -46,6 +47,7 @@ struct kore_runtime kore_native_runtime = {
|
||||
KORE_RUNTIME_NATIVE,
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
.http_request = native_runtime_http_request,
|
||||
.http_request_free = native_runtime_http_request_free,
|
||||
.http_body_chunk = native_runtime_http_body_chunk,
|
||||
.validator = native_runtime_validator,
|
||||
.wsconnect = native_runtime_connect,
|
||||
@ -108,6 +110,13 @@ kore_runtime_http_request(struct kore_runtime_call *rcall,
|
||||
return (rcall->runtime->http_request(rcall->addr, req));
|
||||
}
|
||||
|
||||
void
|
||||
kore_runtime_http_request_free(struct kore_runtime_call *rcall,
|
||||
struct http_request *req)
|
||||
{
|
||||
rcall->runtime->http_request_free(rcall->addr, req);
|
||||
}
|
||||
|
||||
void
|
||||
kore_runtime_http_body_chunk(struct kore_runtime_call *rcall,
|
||||
struct http_request *req, const void *data, size_t len)
|
||||
@ -188,6 +197,15 @@ native_runtime_http_request(void *addr, struct http_request *req)
|
||||
return (cb(req));
|
||||
}
|
||||
|
||||
static void
|
||||
native_runtime_http_request_free(void *addr, struct http_request *req)
|
||||
{
|
||||
int (*cb)(struct http_request *);
|
||||
|
||||
*(void **)&(cb) = addr;
|
||||
cb(req);
|
||||
}
|
||||
|
||||
static void
|
||||
native_runtime_http_body_chunk(void *addr, struct http_request *req,
|
||||
const void *data, size_t len)
|
||||
|
Loading…
x
Reference in New Issue
Block a user