mirror of
https://github.com/jorisvink/kore
synced 2025-03-08 19:19:02 -05:00
Change how routes are configured in Kore.
Routes are now configured in a context per route: route /path { handler handler_name methods get post head validate qs:get id v_id } All route related configurations are per-route, allowing multiple routes for the same path (for different methods). The param context is removed and merged into the route context now so that you use the validate keyword to specify what needs validating.
This commit is contained in:
parent
2576427dc0
commit
e98a4ddab5
2
Makefile
2
Makefile
@ -66,7 +66,7 @@ ifneq ("$(NOHTTP)", "")
|
||||
FEATURES+=-DKORE_NO_HTTP
|
||||
else
|
||||
S_SRC+= src/auth.c src/accesslog.c src/http.c \
|
||||
src/validator.c src/websocket.c
|
||||
src/route.c src/validator.c src/websocket.c
|
||||
endif
|
||||
|
||||
ifneq ("$(PGSQL)", "")
|
||||
|
@ -5,8 +5,6 @@ server tls {
|
||||
}
|
||||
|
||||
workers 1
|
||||
tls_dhparam dh2048.pem
|
||||
|
||||
pledge dns
|
||||
|
||||
domain * {
|
||||
@ -15,6 +13,11 @@ domain * {
|
||||
certfile cert/server.pem
|
||||
certkey cert/key.pem
|
||||
|
||||
route / http
|
||||
route /ftp ftp
|
||||
route / {
|
||||
handler http
|
||||
}
|
||||
|
||||
route /ftp {
|
||||
handler ftp
|
||||
}
|
||||
}
|
||||
|
@ -6,15 +6,21 @@ server tls {
|
||||
|
||||
load ./cookies.so
|
||||
|
||||
tls_dhparam dh2048.pem
|
||||
|
||||
domain * {
|
||||
attach tls
|
||||
|
||||
certfile cert/server.pem
|
||||
certkey cert/key.pem
|
||||
|
||||
route / serve_cookies
|
||||
route /secure serve_cookies
|
||||
route /vault serve_cookies
|
||||
route / {
|
||||
handler serve_cookies
|
||||
}
|
||||
|
||||
route /secure {
|
||||
handler serve_cookies
|
||||
}
|
||||
|
||||
route /vault {
|
||||
handler serve_cookies
|
||||
}
|
||||
}
|
||||
|
@ -5,12 +5,14 @@ server tls {
|
||||
}
|
||||
|
||||
load ./cpp.so
|
||||
tls_dhparam dh2048.pem
|
||||
|
||||
domain * {
|
||||
attach tls
|
||||
|
||||
certfile cert/server.pem
|
||||
certkey cert/key.pem
|
||||
route / page
|
||||
|
||||
route / {
|
||||
handler page
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +0,0 @@
|
||||
-----BEGIN DH PARAMETERS-----
|
||||
MIIBCAKCAQEAn4f4Qn5SudFjEYPWTbUaOTLUH85YWmmPFW1+b5bRa9ygr+1wfamv
|
||||
VKVT7jO8c4msSNikUf6eEfoH0H4VTCaj+Habwu+Sj+I416r3mliMD4SjNsUJrBrY
|
||||
Y0QV3ZUgZz4A8ARk/WwQcRl8+ZXJz34IaLwAcpyNhoV46iHVxW0ty8ND0U4DIku/
|
||||
PNayKimu4BXWXk4RfwNVP59t8DQKqjshZ4fDnbotskmSZ+e+FHrd+Kvrq/WButvV
|
||||
Bzy9fYgnUlJ82g/bziCI83R2xAdtH014fR63MpElkqdNeChb94pPbEdFlNUvYIBN
|
||||
xx2vTUQMqRbB4UdG2zuzzr5j98HDdblQ+wIBAg==
|
||||
-----END DH PARAMETERS-----
|
@ -6,8 +6,6 @@ server tls {
|
||||
|
||||
load ./generic.so example_load
|
||||
|
||||
tls_dhparam dh2048.pem
|
||||
|
||||
http_body_max 1024000000
|
||||
http_body_disk_offload 1024000
|
||||
|
||||
|
@ -2,13 +2,13 @@ Test parameter to integer conversions.
|
||||
|
||||
Run:
|
||||
```
|
||||
# kodev run
|
||||
$ kodev run
|
||||
```
|
||||
|
||||
Test:
|
||||
```
|
||||
# curl -i -k https://127.0.0.1:8888/?id=123123
|
||||
# curl -i -k https://127.0.0.1:8888/?id=-123123
|
||||
$ curl -i -k https://127.0.0.1:8888/?id=123123
|
||||
$ curl -i -k https://127.0.0.1:8888/?id=-123123
|
||||
```
|
||||
|
||||
The correct integer types should only be represented in the output.
|
||||
|
@ -9,8 +9,6 @@ load ./integers.so
|
||||
workers 2
|
||||
worker_max_connections 5000
|
||||
|
||||
tls_dhparam dh2048.pem
|
||||
|
||||
validator v_id regex ^-?[0-9]*.?[0-9]+$
|
||||
|
||||
domain * {
|
||||
@ -18,10 +16,12 @@ domain * {
|
||||
|
||||
certfile cert/server.pem
|
||||
certkey cert/key.pem
|
||||
route / page
|
||||
|
||||
# allowed parameters in the query string for GETs
|
||||
params qs:get / {
|
||||
validate id v_id
|
||||
route / {
|
||||
handler page
|
||||
methods get
|
||||
|
||||
# allowed parameters in the query string for GETs
|
||||
validate get id v_id
|
||||
}
|
||||
}
|
||||
|
@ -6,14 +6,14 @@ server tls {
|
||||
|
||||
load ./json.so
|
||||
|
||||
tls_dhparam dh2048.pem
|
||||
|
||||
domain 127.0.0.1 {
|
||||
attach tls
|
||||
|
||||
certfile cert/server.pem
|
||||
certkey cert/key.pem
|
||||
|
||||
route / page
|
||||
restrict / post
|
||||
route / {
|
||||
handler page
|
||||
methods post
|
||||
}
|
||||
}
|
||||
|
5
examples/json_yajl/.gitignore
vendored
5
examples/json_yajl/.gitignore
vendored
@ -1,5 +0,0 @@
|
||||
*.o
|
||||
.objs
|
||||
json_yajl.so
|
||||
assets.h
|
||||
cert
|
@ -1,21 +0,0 @@
|
||||
This example demonstrates how you can use external libs in your application.
|
||||
|
||||
In this case we link against yajl (Yet Another JSON library) in order to
|
||||
parse a JSON string that was POSTed to the server.
|
||||
|
||||
Take a peek at conf/build.conf for different build flavors and how to
|
||||
link to other libraries.
|
||||
|
||||
Run:
|
||||
```
|
||||
$ kodev run
|
||||
```
|
||||
|
||||
Test:
|
||||
```
|
||||
$ curl -i -k -d '{"foo":{"bar": "Hello world"}}' https://127.0.0.1:8888
|
||||
```
|
||||
|
||||
The result should echo back the foo.bar JSON path value: Hello world.
|
||||
|
||||
The yajl repo is available @ https://github.com/lloyd/yajl
|
@ -1,19 +0,0 @@
|
||||
# json_yajl build config
|
||||
# You can switch flavors using: kodev flavor [newflavor]
|
||||
|
||||
# The cflags below are shared between flavors
|
||||
cflags=-Wall -Wmissing-declarations -Wshadow
|
||||
cflags=-Wstrict-prototypes -Wmissing-prototypes
|
||||
cflags=-Wpointer-arith -Wcast-qual -Wsign-compare
|
||||
|
||||
dev {
|
||||
# These cflags are added to the shared ones when
|
||||
# you build the "dev" flavor.
|
||||
cflags=-g
|
||||
ldflags=-lyajl
|
||||
}
|
||||
|
||||
#prod {
|
||||
# You can specify additional CFLAGS here which are only
|
||||
# included if you build with the "prod" flavor.
|
||||
#}
|
@ -1,18 +0,0 @@
|
||||
# Placeholder configuration
|
||||
|
||||
server tls {
|
||||
bind 127.0.0.1 8888
|
||||
}
|
||||
|
||||
load ./json_yajl.so
|
||||
|
||||
tls_dhparam dh2048.pem
|
||||
|
||||
domain 127.0.0.1 {
|
||||
attach tls
|
||||
|
||||
certfile cert/server.pem
|
||||
certkey cert/key.pem
|
||||
|
||||
route / page
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2018 Joris Vink <joris@coders.se>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <kore/kore.h>
|
||||
#include <kore/http.h>
|
||||
|
||||
#include <yajl/yajl_tree.h>
|
||||
|
||||
int page(struct http_request *);
|
||||
|
||||
int
|
||||
page(struct http_request *req)
|
||||
{
|
||||
ssize_t ret;
|
||||
struct kore_buf *buf;
|
||||
char *body;
|
||||
yajl_val node, v;
|
||||
char eb[1024];
|
||||
u_int8_t data[BUFSIZ];
|
||||
const char *path[] = { "foo", "bar", NULL };
|
||||
|
||||
/* We only allow POST/PUT methods. */
|
||||
if (req->method != HTTP_METHOD_POST &&
|
||||
req->method != HTTP_METHOD_PUT) {
|
||||
http_response_header(req, "allow", "POST, PUT");
|
||||
http_response(req, HTTP_STATUS_METHOD_NOT_ALLOWED, NULL, 0);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the entire received body into a memory buffer.
|
||||
*/
|
||||
buf = kore_buf_alloc(128);
|
||||
for (;;) {
|
||||
ret = http_body_read(req, data, sizeof(data));
|
||||
if (ret == -1) {
|
||||
kore_buf_free(buf);
|
||||
kore_log(LOG_NOTICE, "error reading body");
|
||||
http_response(req, 500, NULL, 0);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
break;
|
||||
|
||||
kore_buf_append(buf, data, ret);
|
||||
}
|
||||
|
||||
/* Grab our body data as a NUL-terminated string. */
|
||||
body = kore_buf_stringify(buf, NULL);
|
||||
|
||||
/* Parse the body via yajl now. */
|
||||
node = yajl_tree_parse(body, eb, sizeof(eb));
|
||||
if (node == NULL) {
|
||||
if (strlen(eb)) {
|
||||
kore_log(LOG_NOTICE, "parse error: %s", eb);
|
||||
} else {
|
||||
kore_log(LOG_NOTICE, "parse error: unknown");
|
||||
}
|
||||
|
||||
kore_buf_free(buf);
|
||||
http_response(req, 400, NULL, 0);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
/* Reuse old buffer, don't need it anymore for body. */
|
||||
kore_buf_reset(buf);
|
||||
|
||||
/* Attempt to grab foo.bar from the JSON tree. */
|
||||
v = yajl_tree_get(node, path, yajl_t_string);
|
||||
if (v == NULL) {
|
||||
kore_buf_appendf(buf, "no such path: foo.bar\n");
|
||||
} else {
|
||||
kore_buf_appendf(buf, "foo.bar = '%s'\n", YAJL_GET_STRING(v));
|
||||
}
|
||||
|
||||
/* Release the JSON tree now. */
|
||||
yajl_tree_free(node);
|
||||
|
||||
/* Respond to the client. */
|
||||
http_response(req, 200, buf->data, buf->offset);
|
||||
kore_buf_free(buf);
|
||||
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
@ -6,14 +6,17 @@ server tls {
|
||||
|
||||
load ./jsonrpc.so
|
||||
|
||||
tls_dhparam dh2048.pem
|
||||
|
||||
domain * {
|
||||
attach tls
|
||||
|
||||
certfile cert/server.pem
|
||||
certkey cert/key.pem
|
||||
|
||||
route / homepage
|
||||
route /v1 v1
|
||||
route / {
|
||||
handler homepage
|
||||
}
|
||||
|
||||
route /v1 {
|
||||
handler v1
|
||||
}
|
||||
}
|
||||
|
@ -6,13 +6,13 @@ server tls {
|
||||
|
||||
load ./memtag.so init
|
||||
|
||||
tls_dhparam dh2048.pem
|
||||
|
||||
domain * {
|
||||
attach tls
|
||||
|
||||
certfile cert/server.pem
|
||||
certkey cert/key.pem
|
||||
|
||||
route / page
|
||||
route / {
|
||||
handler page
|
||||
}
|
||||
}
|
||||
|
@ -5,14 +5,18 @@ server tls {
|
||||
}
|
||||
|
||||
load ./messaging.so init
|
||||
tls_dhparam dh2048.pem
|
||||
workers 4
|
||||
|
||||
domain * {
|
||||
attach tls
|
||||
|
||||
certfile cert/server.pem
|
||||
certkey cert/key.pem
|
||||
route / page
|
||||
route /shutdown page_shutdown
|
||||
|
||||
route / {
|
||||
handler page
|
||||
}
|
||||
|
||||
route /shutdown {
|
||||
handler page_shutdown
|
||||
}
|
||||
}
|
||||
|
@ -4,8 +4,6 @@ server tls {
|
||||
bind 127.0.0.1 8888 connection_setup
|
||||
}
|
||||
|
||||
tls_dhparam dh2048.pem
|
||||
|
||||
domain * {
|
||||
attach tls
|
||||
|
||||
|
@ -6,8 +6,6 @@ server tls {
|
||||
|
||||
load ./parameters.so
|
||||
|
||||
tls_dhparam dh2048.pem
|
||||
|
||||
# The validator used to validate the 'id' parameter
|
||||
# defined below. We'll use a simple regex to make sure
|
||||
# it only matches positive numbers.
|
||||
@ -19,15 +17,10 @@ domain * {
|
||||
certfile cert/server.pem
|
||||
certkey cert/key.pem
|
||||
|
||||
route / page
|
||||
route / {
|
||||
handler page
|
||||
methods get
|
||||
|
||||
# The parameters allowed for "/" (GET method).
|
||||
#
|
||||
# If you would want to declare parameters available
|
||||
# to the page handler for POST, swap the 'get' setting
|
||||
# to 'post' instead, Kore takes care of the rest.
|
||||
params qs:get / {
|
||||
# Validate the id parameter with the v_id validator.
|
||||
validate id v_id
|
||||
validate qs:get id v_id
|
||||
}
|
||||
}
|
||||
|
@ -4,13 +4,15 @@ server tls {
|
||||
bind 127.0.0.1 8888
|
||||
}
|
||||
|
||||
load ./pgsql-sync.so init
|
||||
tls_dhparam dh2048.pem
|
||||
load ./pgsql-sync.so init
|
||||
|
||||
domain * {
|
||||
attach tls
|
||||
|
||||
certfile cert/server.pem
|
||||
certkey cert/key.pem
|
||||
route / page
|
||||
|
||||
route / {
|
||||
handler page
|
||||
}
|
||||
}
|
||||
|
@ -10,8 +10,6 @@ server other {
|
||||
bind 127.0.0.1 8889 connection_new
|
||||
}
|
||||
|
||||
tls_dhparam dh2048.pem
|
||||
|
||||
http_keepalive_time 0
|
||||
|
||||
domain * {
|
||||
@ -20,6 +18,11 @@ domain * {
|
||||
certfile cert/server.pem
|
||||
certkey cert/key.pem
|
||||
|
||||
route / page
|
||||
route /hello hello
|
||||
route / {
|
||||
handler page
|
||||
}
|
||||
|
||||
route /hello {
|
||||
handler hello
|
||||
}
|
||||
}
|
||||
|
@ -4,8 +4,6 @@ server tls {
|
||||
bind 127.0.0.1 8888
|
||||
}
|
||||
|
||||
tls_dhparam dh2048.pem
|
||||
|
||||
websocket_maxframe 65536
|
||||
websocket_timeout 10000
|
||||
|
||||
@ -15,6 +13,12 @@ domain * {
|
||||
certfile cert/server.pem
|
||||
certkey cert/key.pem
|
||||
|
||||
route / page
|
||||
route /connect page_ws_connect
|
||||
route / {
|
||||
handler page
|
||||
}
|
||||
|
||||
route /connect {
|
||||
handler page_ws_connect
|
||||
methods get
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <kore/kore.h>
|
||||
#include <kore/http.h>
|
||||
#include <kore/tasks.h>
|
||||
#include <kore/hooks.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
@ -49,17 +50,12 @@ void pipe_data_available(struct kore_task *);
|
||||
/* Our pipe reader. */
|
||||
struct kore_task pipe_task;
|
||||
|
||||
/* Module init function (see config). */
|
||||
int
|
||||
init(int state)
|
||||
void
|
||||
kore_worker_configure(void)
|
||||
{
|
||||
/* Do not allow reload. */
|
||||
if (state == KORE_MODULE_UNLOAD)
|
||||
return (KORE_RESULT_ERROR);
|
||||
|
||||
/* Only do this on a dedicated worker. */
|
||||
if (worker->id != 1)
|
||||
return (KORE_RESULT_OK);
|
||||
return;
|
||||
|
||||
/* Create our task. */
|
||||
kore_task_create(&pipe_task, pipe_reader);
|
||||
@ -69,8 +65,6 @@ init(int state)
|
||||
|
||||
/* Start the task. */
|
||||
kore_task_run(&pipe_task);
|
||||
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
/* Called whenever we get a new websocket connection. */
|
||||
|
@ -4,10 +4,8 @@ server tls {
|
||||
bind 127.0.0.1 8888
|
||||
}
|
||||
|
||||
load ./sse.so
|
||||
tls_dhparam dh2048.pem
|
||||
|
||||
http_keepalive_time 600
|
||||
load ./sse.so
|
||||
http_keepalive_time 600
|
||||
|
||||
domain * {
|
||||
attach tls
|
||||
@ -15,6 +13,11 @@ domain * {
|
||||
certfile cert/server.pem
|
||||
certkey cert/key.pem
|
||||
|
||||
route / page
|
||||
route /subscribe subscribe
|
||||
route / {
|
||||
handler page
|
||||
}
|
||||
|
||||
route /subscribe {
|
||||
handler subscribe
|
||||
}
|
||||
}
|
||||
|
@ -4,8 +4,6 @@ server tls {
|
||||
bind 127.0.0.1 8888
|
||||
}
|
||||
|
||||
tls_dhparam dh2048.pem
|
||||
|
||||
task_threads 4
|
||||
worker_max_connections 1000
|
||||
http_keepalive_time 0
|
||||
@ -19,14 +17,14 @@ domain * {
|
||||
certkey cert/key.pem
|
||||
accesslog kore_access.log
|
||||
|
||||
route / page_handler
|
||||
route /post_back post_back
|
||||
|
||||
params qs:get / {
|
||||
validate user v_user
|
||||
route / {
|
||||
handler page_handler
|
||||
validate qs:get user v_user
|
||||
}
|
||||
|
||||
params post /post_back {
|
||||
validate user v_user
|
||||
route /post_back {
|
||||
handler post_back
|
||||
methods post
|
||||
validate post user v_user
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
# Kore as a TLS proxy configuration.
|
||||
|
||||
load ./tls-proxy.so
|
||||
tls_dhparam dh2048.pem
|
||||
|
||||
#
|
||||
# Bind the proxy to a given IP and port. For every
|
||||
|
@ -6,8 +6,6 @@ server tls {
|
||||
|
||||
load ./upload.so
|
||||
|
||||
tls_dhparam dh2048.pem
|
||||
|
||||
http_body_max 1024000000
|
||||
http_body_disk_offload 4096
|
||||
|
||||
@ -17,5 +15,7 @@ domain * {
|
||||
certfile cert/server.pem
|
||||
certkey cert/key.pem
|
||||
|
||||
route / page
|
||||
route / {
|
||||
handler page
|
||||
}
|
||||
}
|
||||
|
@ -6,8 +6,6 @@ server tls {
|
||||
|
||||
load ./video_stream.so init
|
||||
|
||||
tls_dhparam dh2048.pem
|
||||
|
||||
http_keepalive_time 600
|
||||
|
||||
domain * {
|
||||
@ -17,6 +15,11 @@ domain * {
|
||||
certkey cert/key.pem
|
||||
accesslog access.log
|
||||
|
||||
route / asset_serve_video_html
|
||||
route ^/[a-z]*.[a-z0-9]{3}$ video_stream
|
||||
route / {
|
||||
handler asset_serve_video_html
|
||||
}
|
||||
|
||||
route ^/[a-z]*.[a-z0-9]{3}$ {
|
||||
handler video_stream
|
||||
}
|
||||
}
|
||||
|
@ -6,8 +6,6 @@ server tls {
|
||||
|
||||
load ./websocket.so
|
||||
|
||||
tls_dhparam dh2048.pem
|
||||
|
||||
# Increase workers so connections are spread
|
||||
# across them to demonstrate WEBSOCKET_BROADCAST_GLOBAL.
|
||||
workers 4
|
||||
@ -21,6 +19,11 @@ domain * {
|
||||
certfile cert/server.pem
|
||||
certkey cert/key.pem
|
||||
|
||||
route / page
|
||||
route /connect page_ws_connect
|
||||
route / {
|
||||
handler page
|
||||
}
|
||||
|
||||
route /connect {
|
||||
handler page_ws_connect
|
||||
}
|
||||
}
|
||||
|
@ -268,7 +268,7 @@ struct http_request {
|
||||
void *hdlr_extra;
|
||||
size_t state_len;
|
||||
char *query_string;
|
||||
struct kore_module_handle *hdlr;
|
||||
struct kore_route *rt;
|
||||
struct http_runlock_queue *runlock;
|
||||
void (*onfree)(struct http_request *);
|
||||
|
||||
|
@ -304,6 +304,33 @@ struct kore_runtime_call {
|
||||
struct kore_runtime *runtime;
|
||||
};
|
||||
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
|
||||
struct kore_route_params {
|
||||
char *name;
|
||||
int flags;
|
||||
u_int8_t method;
|
||||
struct kore_validator *validator;
|
||||
|
||||
TAILQ_ENTRY(kore_route_params) list;
|
||||
};
|
||||
|
||||
struct kore_route {
|
||||
char *path;
|
||||
char *func;
|
||||
int type;
|
||||
int errors;
|
||||
regex_t rctx;
|
||||
struct kore_domain *dom;
|
||||
struct kore_runtime_call *rcall;
|
||||
struct kore_auth *auth;
|
||||
int methods;
|
||||
TAILQ_HEAD(, kore_route_params) params;
|
||||
TAILQ_ENTRY(kore_route) list;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
struct kore_domain {
|
||||
u_int16_t id;
|
||||
int logerr;
|
||||
@ -327,7 +354,7 @@ struct kore_domain {
|
||||
SSL_CTX *ssl_ctx;
|
||||
int x509_verify_depth;
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
TAILQ_HEAD(, kore_module_handle) handlers;
|
||||
TAILQ_HEAD(, kore_route) routes;
|
||||
TAILQ_HEAD(, http_redirect) redirects;
|
||||
#endif
|
||||
TAILQ_ENTRY(kore_domain) list;
|
||||
@ -363,15 +390,6 @@ LIST_HEAD(kore_server_list, kore_server);
|
||||
|
||||
#define KORE_PARAMS_QUERY_STRING 0x0001
|
||||
|
||||
struct kore_handler_params {
|
||||
char *name;
|
||||
int flags;
|
||||
u_int8_t method;
|
||||
struct kore_validator *validator;
|
||||
|
||||
TAILQ_ENTRY(kore_handler_params) list;
|
||||
};
|
||||
|
||||
#define KORE_AUTH_TYPE_COOKIE 1
|
||||
#define KORE_AUTH_TYPE_HEADER 2
|
||||
#define KORE_AUTH_TYPE_REQUEST 3
|
||||
@ -420,23 +438,6 @@ struct kore_module {
|
||||
TAILQ_ENTRY(kore_module) list;
|
||||
};
|
||||
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
|
||||
struct kore_module_handle {
|
||||
char *path;
|
||||
char *func;
|
||||
int type;
|
||||
int errors;
|
||||
regex_t rctx;
|
||||
struct kore_domain *dom;
|
||||
struct kore_runtime_call *rcall;
|
||||
struct kore_auth *auth;
|
||||
int methods;
|
||||
TAILQ_HEAD(, kore_handler_params) params;
|
||||
TAILQ_ENTRY(kore_module_handle) list;
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The workers get a 128KB log buffer per worker, and parent will fetch their
|
||||
* logs when it reached at least 75% of that or if its been > 1 second since
|
||||
@ -471,7 +472,7 @@ struct kore_worker {
|
||||
u_int8_t has_lock;
|
||||
int restarted;
|
||||
u_int64_t time_locked;
|
||||
struct kore_module_handle *active_hdlr;
|
||||
struct kore_route *active_route;
|
||||
struct kore_privsep *ps;
|
||||
|
||||
/* Used by the workers to store accesslogs. */
|
||||
@ -959,12 +960,16 @@ int kore_domain_attach(struct kore_domain *, struct kore_server *);
|
||||
void kore_domain_tlsinit(struct kore_domain *, int,
|
||||
const void *, size_t);
|
||||
void kore_domain_crl_add(struct kore_domain *, const void *, size_t);
|
||||
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
int kore_module_handler_new(struct kore_domain *, const char *,
|
||||
const char *, const char *, int);
|
||||
void kore_module_handler_free(struct kore_module_handle *);
|
||||
int kore_module_handler_find(struct http_request *,
|
||||
struct kore_domain *, int, struct kore_module_handle **);
|
||||
void kore_route_reload(void);
|
||||
void kore_route_free(struct kore_route *);
|
||||
void kore_route_callback(struct kore_route *, const char *);
|
||||
|
||||
struct kore_route *kore_route_create(struct kore_domain *,
|
||||
const char *, int);
|
||||
int kore_route_lookup(struct http_request *,
|
||||
struct kore_domain *, int, struct kore_route **);
|
||||
#endif
|
||||
|
||||
struct kore_runtime_call *kore_runtime_getcall(const char *);
|
||||
|
@ -195,7 +195,7 @@ kore_accesslog(struct http_request *req)
|
||||
}
|
||||
|
||||
hdr->loglen = len;
|
||||
hdr->domain = req->hdlr->dom->id;
|
||||
hdr->domain = req->rt->dom->id;
|
||||
|
||||
worker->lb.offset += (size_t)len;
|
||||
break;
|
||||
|
@ -293,7 +293,10 @@ static const char *config_data =
|
||||
"\tcertfile\tcert/server.pem\n"
|
||||
"\tcertkey\t\tcert/key.pem\n"
|
||||
"\n"
|
||||
"\troute\t/\tpage\n"
|
||||
"\troute / {\n"
|
||||
"\t\thandler page\n"
|
||||
"\t}\n"
|
||||
"\n"
|
||||
"}\n";
|
||||
|
||||
static const char *build_data =
|
||||
|
503
src/config.c
503
src/config.c
File diff suppressed because it is too large
Load Diff
25
src/domain.c
25
src/domain.c
@ -131,8 +131,8 @@ kore_domain_new(const char *domain)
|
||||
dom->domain = kore_strdup(domain);
|
||||
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
TAILQ_INIT(&(dom->handlers));
|
||||
TAILQ_INIT(&(dom->redirects));
|
||||
TAILQ_INIT(&dom->routes);
|
||||
TAILQ_INIT(&dom->redirects);
|
||||
#endif
|
||||
|
||||
if (dom->id < KORE_DOMAIN_CACHE) {
|
||||
@ -174,8 +174,8 @@ void
|
||||
kore_domain_free(struct kore_domain *dom)
|
||||
{
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
struct kore_route *rt;
|
||||
struct http_redirect *rdr;
|
||||
struct kore_module_handle *hdlr;
|
||||
#endif
|
||||
if (dom == NULL)
|
||||
return;
|
||||
@ -190,20 +190,17 @@ kore_domain_free(struct kore_domain *dom)
|
||||
|
||||
if (dom->ssl_ctx != NULL)
|
||||
SSL_CTX_free(dom->ssl_ctx);
|
||||
if (dom->cafile != NULL)
|
||||
kore_free(dom->cafile);
|
||||
if (dom->certkey != NULL)
|
||||
kore_free(dom->certkey);
|
||||
if (dom->certfile != NULL)
|
||||
kore_free(dom->certfile);
|
||||
if (dom->crlfile != NULL)
|
||||
kore_free(dom->crlfile);
|
||||
|
||||
kore_free(dom->cafile);
|
||||
kore_free(dom->certkey);
|
||||
kore_free(dom->certfile);
|
||||
kore_free(dom->crlfile);
|
||||
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
/* Drop all handlers associated with this domain */
|
||||
while ((hdlr = TAILQ_FIRST(&(dom->handlers))) != NULL) {
|
||||
TAILQ_REMOVE(&(dom->handlers), hdlr, list);
|
||||
kore_module_handler_free(hdlr);
|
||||
while ((rt = TAILQ_FIRST(&dom->routes)) != NULL) {
|
||||
TAILQ_REMOVE(&dom->routes, rt, list);
|
||||
kore_route_free(rt);
|
||||
}
|
||||
|
||||
while ((rdr = TAILQ_FIRST(&(dom->redirects))) != NULL) {
|
||||
|
@ -58,7 +58,7 @@ kore_filemap_create(struct kore_domain *dom, const char *path, const char *root)
|
||||
size_t sz;
|
||||
struct stat st;
|
||||
int len;
|
||||
struct kore_module_handle *hdlr;
|
||||
struct kore_route *rt;
|
||||
struct filemap_entry *entry;
|
||||
char regex[1024], fpath[PATH_MAX];
|
||||
|
||||
@ -86,20 +86,11 @@ kore_filemap_create(struct kore_domain *dom, const char *path, const char *root)
|
||||
if (len == -1 || (size_t)len >= sizeof(regex))
|
||||
fatal("kore_filemap_create: buffer too small");
|
||||
|
||||
if (!kore_module_handler_new(dom, regex, "filemap_resolve",
|
||||
NULL, HANDLER_TYPE_DYNAMIC))
|
||||
if ((rt = kore_route_create(dom, regex, HANDLER_TYPE_DYNAMIC)) == NULL)
|
||||
return (KORE_RESULT_ERROR);
|
||||
|
||||
hdlr = NULL;
|
||||
TAILQ_FOREACH(hdlr, &dom->handlers, list) {
|
||||
if (!strcmp(hdlr->path, regex))
|
||||
break;
|
||||
}
|
||||
|
||||
if (hdlr == NULL)
|
||||
fatal("couldn't find newly created handler for filemap");
|
||||
|
||||
hdlr->methods = HTTP_METHOD_GET | HTTP_METHOD_HEAD;
|
||||
kore_route_callback(rt, "filemap_resolve");
|
||||
rt->methods = HTTP_METHOD_GET | HTTP_METHOD_HEAD;
|
||||
|
||||
entry = kore_calloc(1, sizeof(*entry));
|
||||
entry->domain = dom;
|
||||
@ -151,7 +142,7 @@ filemap_resolve(struct http_request *req)
|
||||
best_len = 0;
|
||||
|
||||
TAILQ_FOREACH(entry, &maps, list) {
|
||||
if (entry->domain != req->hdlr->dom)
|
||||
if (entry->domain != req->rt->dom)
|
||||
continue;
|
||||
|
||||
if (!strncmp(entry->root, req->path, entry->root_len)) {
|
||||
|
18
src/http.c
18
src/http.c
@ -345,18 +345,18 @@ http_process_request(struct http_request *req)
|
||||
kore_debug("http_process_request: %p->%p (%s)",
|
||||
req->owner, req, req->path);
|
||||
|
||||
if (req->flags & HTTP_REQUEST_DELETE || req->hdlr == NULL)
|
||||
if (req->flags & HTTP_REQUEST_DELETE || req->rt == NULL)
|
||||
return;
|
||||
|
||||
req->start = kore_time_ms();
|
||||
if (req->hdlr->auth != NULL && !(req->flags & HTTP_REQUEST_AUTHED))
|
||||
r = kore_auth_run(req, req->hdlr->auth);
|
||||
if (req->rt->auth != NULL && !(req->flags & HTTP_REQUEST_AUTHED))
|
||||
r = kore_auth_run(req, req->rt->auth);
|
||||
else
|
||||
r = KORE_RESULT_OK;
|
||||
|
||||
switch (r) {
|
||||
case KORE_RESULT_OK:
|
||||
r = kore_runtime_http_request(req->hdlr->rcall, req);
|
||||
r = kore_runtime_http_request(req->rt->rcall, req);
|
||||
break;
|
||||
case KORE_RESULT_RETRY:
|
||||
break;
|
||||
@ -389,7 +389,7 @@ http_process_request(struct http_request *req)
|
||||
fatal("A page handler returned an unknown result: %d", r);
|
||||
}
|
||||
|
||||
if (req->hdlr->dom->accesslog)
|
||||
if (req->rt->dom->accesslog)
|
||||
kore_accesslog(req);
|
||||
|
||||
req->flags |= HTTP_REQUEST_DELETE;
|
||||
@ -2103,7 +2103,7 @@ http_request_new(struct connection *c, const char *host,
|
||||
}
|
||||
|
||||
/* Checked further down below if we need to 404. */
|
||||
exists = kore_module_handler_find(req, dom, m, &req->hdlr);
|
||||
exists = kore_route_lookup(req, dom, m, &req->rt);
|
||||
|
||||
TAILQ_INIT(&(req->resp_headers));
|
||||
TAILQ_INIT(&(req->req_headers));
|
||||
@ -2135,7 +2135,7 @@ http_request_new(struct connection *c, const char *host,
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (req->hdlr == NULL) {
|
||||
if (req->rt == NULL) {
|
||||
http_request_free(req);
|
||||
http_error_response(c, HTTP_STATUS_METHOD_NOT_ALLOWED);
|
||||
return (NULL);
|
||||
@ -2339,14 +2339,14 @@ http_argument_add(struct http_request *req, char *name, char *value, int qs,
|
||||
int decode)
|
||||
{
|
||||
struct http_arg *q;
|
||||
struct kore_handler_params *p;
|
||||
struct kore_route_params *p;
|
||||
|
||||
if (decode) {
|
||||
if (!http_argument_urldecode(name))
|
||||
return;
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(p, &(req->hdlr->params), list) {
|
||||
TAILQ_FOREACH(p, &req->rt->params, list) {
|
||||
if (qs == 1 && !(p->flags & KORE_PARAMS_QUERY_STRING))
|
||||
continue;
|
||||
if (qs == 0 && (p->flags & KORE_PARAMS_QUERY_STRING))
|
||||
|
128
src/module.c
128
src/module.c
@ -135,11 +135,6 @@ kore_module_reload(int cbs)
|
||||
{
|
||||
struct stat st;
|
||||
int ret;
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
struct kore_server *srv;
|
||||
struct kore_domain *dom;
|
||||
struct kore_module_handle *hdlr;
|
||||
#endif
|
||||
struct kore_module *module;
|
||||
|
||||
TAILQ_FOREACH(module, &modules, list) {
|
||||
@ -183,22 +178,7 @@ kore_module_reload(int cbs)
|
||||
}
|
||||
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
LIST_FOREACH(srv, &kore_servers, list) {
|
||||
TAILQ_FOREACH(dom, &srv->domains, list) {
|
||||
TAILQ_FOREACH(hdlr, &(dom->handlers), list) {
|
||||
kore_free(hdlr->rcall);
|
||||
hdlr->rcall = kore_runtime_getcall(hdlr->func);
|
||||
if (hdlr->rcall == NULL) {
|
||||
fatal("no function '%s' found",
|
||||
hdlr->func);
|
||||
}
|
||||
hdlr->errors = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
kore_route_reload();
|
||||
kore_validator_reload();
|
||||
#endif
|
||||
}
|
||||
@ -212,112 +192,6 @@ kore_module_loaded(void)
|
||||
return (1);
|
||||
}
|
||||
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
int
|
||||
kore_module_handler_new(struct kore_domain *dom, const char *path,
|
||||
const char *func, const char *auth, int type)
|
||||
{
|
||||
struct kore_auth *ap;
|
||||
struct kore_module_handle *hdlr;
|
||||
|
||||
if (auth != NULL) {
|
||||
if ((ap = kore_auth_lookup(auth)) == NULL)
|
||||
fatal("no authentication block '%s' found", auth);
|
||||
} else {
|
||||
ap = NULL;
|
||||
}
|
||||
|
||||
hdlr = kore_malloc(sizeof(*hdlr));
|
||||
hdlr->auth = ap;
|
||||
hdlr->dom = dom;
|
||||
hdlr->errors = 0;
|
||||
hdlr->type = type;
|
||||
hdlr->path = kore_strdup(path);
|
||||
hdlr->func = kore_strdup(func);
|
||||
hdlr->methods = HTTP_METHOD_ALL;
|
||||
|
||||
TAILQ_INIT(&(hdlr->params));
|
||||
|
||||
if ((hdlr->rcall = kore_runtime_getcall(func)) == NULL) {
|
||||
kore_module_handler_free(hdlr);
|
||||
kore_log(LOG_ERR, "function '%s' not found", func);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
if (hdlr->type == HANDLER_TYPE_DYNAMIC) {
|
||||
if (regcomp(&(hdlr->rctx), hdlr->path,
|
||||
REG_EXTENDED | REG_NOSUB)) {
|
||||
kore_module_handler_free(hdlr);
|
||||
kore_debug("regcomp() on %s failed", path);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
TAILQ_INSERT_TAIL(&(dom->handlers), hdlr, list);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
void
|
||||
kore_module_handler_free(struct kore_module_handle *hdlr)
|
||||
{
|
||||
struct kore_handler_params *param;
|
||||
|
||||
if (hdlr == NULL)
|
||||
return;
|
||||
|
||||
if (hdlr->func != NULL)
|
||||
kore_free(hdlr->func);
|
||||
if (hdlr->path != NULL)
|
||||
kore_free(hdlr->path);
|
||||
if (hdlr->type == HANDLER_TYPE_DYNAMIC)
|
||||
regfree(&(hdlr->rctx));
|
||||
|
||||
/* Drop all validators associated with this handler */
|
||||
while ((param = TAILQ_FIRST(&(hdlr->params))) != NULL) {
|
||||
TAILQ_REMOVE(&(hdlr->params), param, list);
|
||||
if (param->name != NULL)
|
||||
kore_free(param->name);
|
||||
kore_free(param);
|
||||
}
|
||||
|
||||
kore_free(hdlr);
|
||||
}
|
||||
|
||||
int
|
||||
kore_module_handler_find(struct http_request *req, struct kore_domain *dom,
|
||||
int method, struct kore_module_handle **out)
|
||||
{
|
||||
struct kore_module_handle *hdlr;
|
||||
int exists;
|
||||
|
||||
exists = 0;
|
||||
*out = NULL;
|
||||
|
||||
TAILQ_FOREACH(hdlr, &(dom->handlers), list) {
|
||||
if (hdlr->type == HANDLER_TYPE_STATIC) {
|
||||
if (!strcmp(hdlr->path, req->path)) {
|
||||
if (hdlr->methods & method) {
|
||||
*out = hdlr;
|
||||
return (1);
|
||||
}
|
||||
exists++;
|
||||
}
|
||||
} else {
|
||||
if (!regexec(&(hdlr->rctx), req->path,
|
||||
HTTP_CAPTURE_GROUPS, req->cgroups, 0)) {
|
||||
if (hdlr->methods & method) {
|
||||
*out = hdlr;
|
||||
return (1);
|
||||
}
|
||||
exists++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (exists);
|
||||
}
|
||||
#endif /* !KORE_NO_HTTP */
|
||||
|
||||
void *
|
||||
kore_module_getsym(const char *symbol, struct kore_runtime **runtime)
|
||||
{
|
||||
|
87
src/python.c
87
src/python.c
@ -82,13 +82,11 @@ static struct python_coro *python_coro_create(PyObject *,
|
||||
static struct kore_domain *python_route_domain_resolve(struct pyroute *);
|
||||
|
||||
static int python_route_install(struct pyroute *);
|
||||
static int python_route_params(PyObject *,
|
||||
struct kore_module_handle *, const char *,
|
||||
int, int);
|
||||
static int python_route_params(PyObject *, struct kore_route *,
|
||||
const char *, int, int);
|
||||
static int python_route_methods(PyObject *, PyObject *,
|
||||
struct kore_module_handle *);
|
||||
static int python_route_auth(PyObject *,
|
||||
struct kore_module_handle *);
|
||||
struct kore_route *);
|
||||
static int python_route_auth(PyObject *, struct kore_route *);
|
||||
|
||||
static int python_coro_run(struct python_coro *);
|
||||
static void python_coro_wakeup(struct python_coro *);
|
||||
@ -1250,7 +1248,7 @@ python_runtime_http_request(void *addr, struct http_request *req)
|
||||
callable = (PyObject *)addr;
|
||||
|
||||
/* starts at 1 to skip the full path. */
|
||||
if (req->hdlr->type == HANDLER_TYPE_DYNAMIC) {
|
||||
if (req->rt->type == HANDLER_TYPE_DYNAMIC) {
|
||||
for (idx = 1; idx < HTTP_CAPTURE_GROUPS - 1; idx++) {
|
||||
if (req->cgroups[idx].rm_so == -1 ||
|
||||
req->cgroups[idx].rm_eo == -1)
|
||||
@ -5211,7 +5209,7 @@ python_route_install(struct pyroute *route)
|
||||
{
|
||||
const char *val;
|
||||
struct kore_domain *domain;
|
||||
struct kore_module_handle *hdlr, *entry;
|
||||
struct kore_route *rt, *entry;
|
||||
PyObject *kwargs, *repr, *obj;
|
||||
|
||||
if ((repr = PyObject_Repr(route->func)) == NULL) {
|
||||
@ -5221,56 +5219,56 @@ python_route_install(struct pyroute *route)
|
||||
|
||||
domain = python_route_domain_resolve(route);
|
||||
|
||||
hdlr = kore_calloc(1, sizeof(*hdlr));
|
||||
hdlr->dom = domain;
|
||||
hdlr->methods = HTTP_METHOD_ALL;
|
||||
hdlr->path = kore_strdup(route->path);
|
||||
rt = kore_calloc(1, sizeof(*rt));
|
||||
rt->dom = domain;
|
||||
rt->methods = HTTP_METHOD_ALL;
|
||||
rt->path = kore_strdup(route->path);
|
||||
|
||||
TAILQ_INIT(&hdlr->params);
|
||||
TAILQ_INIT(&rt->params);
|
||||
|
||||
val = PyUnicode_AsUTF8(repr);
|
||||
hdlr->func = kore_strdup(val);
|
||||
rt->func = kore_strdup(val);
|
||||
|
||||
kwargs = route->kwargs;
|
||||
|
||||
hdlr->rcall = kore_calloc(1, sizeof(struct kore_runtime_call));
|
||||
hdlr->rcall->addr = route->func;
|
||||
hdlr->rcall->runtime = &kore_python_runtime;
|
||||
Py_INCREF(hdlr->rcall->addr);
|
||||
rt->rcall = kore_calloc(1, sizeof(struct kore_runtime_call));
|
||||
rt->rcall->addr = route->func;
|
||||
rt->rcall->runtime = &kore_python_runtime;
|
||||
Py_INCREF(rt->rcall->addr);
|
||||
|
||||
if (kwargs != NULL) {
|
||||
if ((obj = PyDict_GetItemString(kwargs, "methods")) != NULL) {
|
||||
if (!python_route_methods(obj, kwargs, hdlr)) {
|
||||
if (!python_route_methods(obj, kwargs, rt)) {
|
||||
kore_python_log_error("python_route_install");
|
||||
kore_module_handler_free(hdlr);
|
||||
kore_route_free(rt);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if ((obj = PyDict_GetItemString(kwargs, "auth")) != NULL) {
|
||||
if (!python_route_auth(obj, hdlr)) {
|
||||
if (!python_route_auth(obj, rt)) {
|
||||
kore_python_log_error("python_route_install");
|
||||
kore_module_handler_free(hdlr);
|
||||
kore_route_free(rt);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hdlr->path[0] == '/') {
|
||||
hdlr->type = HANDLER_TYPE_STATIC;
|
||||
if (rt->path[0] == '/') {
|
||||
rt->type = HANDLER_TYPE_STATIC;
|
||||
} else {
|
||||
hdlr->type = HANDLER_TYPE_DYNAMIC;
|
||||
if (regcomp(&hdlr->rctx, hdlr->path, REG_EXTENDED))
|
||||
fatal("failed to compile regex for '%s'", hdlr->path);
|
||||
rt->type = HANDLER_TYPE_DYNAMIC;
|
||||
if (regcomp(&rt->rctx, rt->path, REG_EXTENDED))
|
||||
fatal("failed to compile regex for '%s'", rt->path);
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(entry, &domain->handlers, list) {
|
||||
if (!strcmp(entry->path, hdlr->path) &&
|
||||
(entry->methods & hdlr->methods))
|
||||
TAILQ_FOREACH(entry, &domain->routes, list) {
|
||||
if (!strcmp(entry->path, rt->path) &&
|
||||
(entry->methods & rt->methods))
|
||||
fatal("duplicate route for '%s'", route->path);
|
||||
}
|
||||
|
||||
TAILQ_INSERT_TAIL(&domain->handlers, hdlr, list);
|
||||
TAILQ_INSERT_TAIL(&domain->routes, rt, list);
|
||||
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
@ -5312,8 +5310,7 @@ python_route_domain_resolve(struct pyroute *route)
|
||||
}
|
||||
|
||||
static int
|
||||
python_route_methods(PyObject *obj, PyObject *kwargs,
|
||||
struct kore_module_handle *hdlr)
|
||||
python_route_methods(PyObject *obj, PyObject *kwargs, struct kore_route *rt)
|
||||
{
|
||||
const char *val;
|
||||
PyObject *item;
|
||||
@ -5323,7 +5320,7 @@ python_route_methods(PyObject *obj, PyObject *kwargs,
|
||||
if (!PyList_CheckExact(obj))
|
||||
return (KORE_RESULT_ERROR);
|
||||
|
||||
hdlr->methods = 0;
|
||||
rt->methods = 0;
|
||||
list_len = PyList_Size(obj);
|
||||
|
||||
for (idx = 0; idx < list_len; idx++) {
|
||||
@ -5339,14 +5336,14 @@ python_route_methods(PyObject *obj, PyObject *kwargs,
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
hdlr->methods |= method;
|
||||
rt->methods |= method;
|
||||
if (method == HTTP_METHOD_GET)
|
||||
hdlr->methods |= HTTP_METHOD_HEAD;
|
||||
rt->methods |= HTTP_METHOD_HEAD;
|
||||
|
||||
if (!python_route_params(kwargs, hdlr, val, method, 0))
|
||||
if (!python_route_params(kwargs, rt, val, method, 0))
|
||||
return (KORE_RESULT_ERROR);
|
||||
|
||||
if (!python_route_params(kwargs, hdlr, "qs", method, 1))
|
||||
if (!python_route_params(kwargs, rt, "qs", method, 1))
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
@ -5354,14 +5351,14 @@ python_route_methods(PyObject *obj, PyObject *kwargs,
|
||||
}
|
||||
|
||||
static int
|
||||
python_route_params(PyObject *kwargs, struct kore_module_handle *hdlr,
|
||||
python_route_params(PyObject *kwargs, struct kore_route *rt,
|
||||
const char *method, int type, int qs)
|
||||
{
|
||||
Py_ssize_t idx;
|
||||
const char *val;
|
||||
int vtype;
|
||||
struct kore_validator *vldr;
|
||||
struct kore_handler_params *param;
|
||||
struct kore_route_params *param;
|
||||
PyObject *obj, *key, *item;
|
||||
|
||||
if ((obj = PyDict_GetItemString(kwargs, method)) == NULL)
|
||||
@ -5418,14 +5415,14 @@ python_route_params(PyObject *kwargs, struct kore_module_handle *hdlr,
|
||||
if (type == HTTP_METHOD_GET || qs == 1)
|
||||
param->flags = KORE_PARAMS_QUERY_STRING;
|
||||
|
||||
TAILQ_INSERT_TAIL(&hdlr->params, param, list);
|
||||
TAILQ_INSERT_TAIL(&rt->params, param, list);
|
||||
}
|
||||
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
python_route_auth(PyObject *dict, struct kore_module_handle *hdlr)
|
||||
python_route_auth(PyObject *dict, struct kore_route *rt)
|
||||
{
|
||||
int type;
|
||||
struct kore_auth *auth;
|
||||
@ -5449,7 +5446,7 @@ python_route_auth(PyObject *dict, struct kore_module_handle *hdlr)
|
||||
} else {
|
||||
PyErr_Format(PyExc_RuntimeError,
|
||||
"invalid 'type' (%s) in auth dictionary for '%s'",
|
||||
value, hdlr->path);
|
||||
value, rt->path);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
@ -5464,7 +5461,7 @@ python_route_auth(PyObject *dict, struct kore_module_handle *hdlr)
|
||||
if ((obj = PyDict_GetItemString(dict, "verify")) == NULL ||
|
||||
!PyCallable_Check(obj)) {
|
||||
PyErr_Format(PyExc_RuntimeError,
|
||||
"missing 'verify' in auth dictionary for '%s'", hdlr->path);
|
||||
"missing 'verify' in auth dictionary for '%s'", rt->path);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
@ -5495,7 +5492,7 @@ python_route_auth(PyObject *dict, struct kore_module_handle *hdlr)
|
||||
Py_DECREF(repr);
|
||||
|
||||
auth->validator = vldr;
|
||||
hdlr->auth = auth;
|
||||
rt->auth = auth;
|
||||
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
138
src/route.c
Normal file
138
src/route.c
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Joris Vink <joris@coders.se>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "kore.h"
|
||||
#include "http.h"
|
||||
|
||||
struct kore_route *
|
||||
kore_route_create(struct kore_domain *dom, const char *path, int type)
|
||||
{
|
||||
struct kore_route *rt;
|
||||
|
||||
rt = kore_calloc(1, sizeof(*rt));
|
||||
rt->dom = dom;
|
||||
rt->type = type;
|
||||
rt->path = kore_strdup(path);
|
||||
rt->methods = HTTP_METHOD_ALL;
|
||||
|
||||
TAILQ_INIT(&rt->params);
|
||||
|
||||
if (rt->type == HANDLER_TYPE_DYNAMIC) {
|
||||
if (regcomp(&rt->rctx, rt->path, REG_EXTENDED | REG_NOSUB)) {
|
||||
kore_route_free(rt);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
TAILQ_INSERT_TAIL(&dom->routes, rt, list);
|
||||
|
||||
return (rt);
|
||||
}
|
||||
|
||||
void
|
||||
kore_route_free(struct kore_route *rt)
|
||||
{
|
||||
struct kore_route_params *param;
|
||||
|
||||
if (rt == NULL)
|
||||
return;
|
||||
|
||||
kore_free(rt->func);
|
||||
kore_free(rt->path);
|
||||
|
||||
if (rt->type == HANDLER_TYPE_DYNAMIC)
|
||||
regfree(&rt->rctx);
|
||||
|
||||
/* Drop all validators associated with this handler */
|
||||
while ((param = TAILQ_FIRST(&rt->params)) != NULL) {
|
||||
TAILQ_REMOVE(&rt->params, param, list);
|
||||
kore_free(param->name);
|
||||
kore_free(param);
|
||||
}
|
||||
|
||||
kore_free(rt);
|
||||
}
|
||||
|
||||
void
|
||||
kore_route_callback(struct kore_route *rt, const char *func)
|
||||
{
|
||||
if ((rt->rcall = kore_runtime_getcall(func)) == NULL)
|
||||
fatal("callback '%s' for '%s' not found", func, rt->path);
|
||||
|
||||
kore_free(rt->func);
|
||||
rt->func = kore_strdup(func);
|
||||
}
|
||||
|
||||
int
|
||||
kore_route_lookup(struct http_request *req, struct kore_domain *dom,
|
||||
int method, struct kore_route **out)
|
||||
{
|
||||
struct kore_route *rt;
|
||||
int exists;
|
||||
|
||||
exists = 0;
|
||||
*out = NULL;
|
||||
|
||||
TAILQ_FOREACH(rt, &dom->routes, list) {
|
||||
if (rt->type == HANDLER_TYPE_STATIC) {
|
||||
if (!strcmp(rt->path, req->path)) {
|
||||
if (rt->methods & method) {
|
||||
*out = rt;
|
||||
return (1);
|
||||
}
|
||||
exists++;
|
||||
}
|
||||
} else {
|
||||
if (!regexec(&rt->rctx, req->path,
|
||||
HTTP_CAPTURE_GROUPS, req->cgroups, 0)) {
|
||||
if (rt->methods & method) {
|
||||
*out = rt;
|
||||
return (1);
|
||||
}
|
||||
exists++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (exists);
|
||||
}
|
||||
|
||||
void
|
||||
kore_route_reload(void)
|
||||
{
|
||||
struct kore_route *rt;
|
||||
struct kore_server *srv;
|
||||
struct kore_domain *dom;
|
||||
|
||||
LIST_FOREACH(srv, &kore_servers, list) {
|
||||
TAILQ_FOREACH(dom, &srv->domains, list) {
|
||||
TAILQ_FOREACH(rt, &dom->routes, list) {
|
||||
kore_free(rt->rcall);
|
||||
rt->rcall = kore_runtime_getcall(rt->func);
|
||||
if (rt->rcall == NULL) {
|
||||
fatal("no function '%s' for route '%s'",
|
||||
rt->func, rt->path);
|
||||
}
|
||||
rt->errors = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
src/worker.c
19
src/worker.c
@ -191,10 +191,11 @@ kore_worker_spawn(u_int16_t idx, u_int16_t id, u_int16_t cpu)
|
||||
kw = WORKER(idx);
|
||||
kw->id = id;
|
||||
kw->cpu = cpu;
|
||||
kw->has_lock = 0;
|
||||
kw->active_hdlr = NULL;
|
||||
kw->running = 1;
|
||||
|
||||
kw->ready = 0;
|
||||
kw->has_lock = 0;
|
||||
kw->active_route = NULL;
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, kw->pipe) == -1)
|
||||
fatal("socketpair(): %s", errno_s);
|
||||
@ -743,7 +744,7 @@ kore_worker_started(void)
|
||||
|
||||
if (!kore_quiet) {
|
||||
kore_log(LOG_NOTICE,
|
||||
"process started (#%d %s=%s%s%s)",
|
||||
"started (#%d %s=%s%s%s)",
|
||||
getpid(), chroot, worker->ps->root,
|
||||
worker->ps->skip_runas ? "" : " user=",
|
||||
worker->ps->skip_runas ? "" : worker->ps->runas);
|
||||
@ -797,8 +798,8 @@ worker_reaper(pid_t pid, int status)
|
||||
|
||||
func = "none";
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
if (kw->active_hdlr != NULL)
|
||||
func = kw->active_hdlr->func;
|
||||
if (kw->active_route != NULL)
|
||||
func = kw->active_route->func;
|
||||
#endif
|
||||
kore_log(LOG_NOTICE,
|
||||
"worker %d (pid: %d) (hdlr: %s) gone",
|
||||
@ -828,12 +829,12 @@ worker_reaper(pid_t pid, int status)
|
||||
worker_unlock();
|
||||
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
if (kw->active_hdlr != NULL) {
|
||||
kw->active_hdlr->errors++;
|
||||
if (kw->active_route != NULL) {
|
||||
kw->active_route->errors++;
|
||||
kore_log(LOG_NOTICE,
|
||||
"hdlr %s has caused %d error(s)",
|
||||
kw->active_hdlr->func,
|
||||
kw->active_hdlr->errors);
|
||||
kw->active_route->func,
|
||||
kw->active_route->errors);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user