Skip to content

Commit

Permalink
feat: load a plugin using wildcards
Browse files Browse the repository at this point in the history
```
struct uh_plugin_handler uh_plugin_handler = {
    .path = "^/test$",
    .wildcard = true,
    .handler = test_handler
};
```

Signed-off-by: Jianhui Zhao <zhaojh329@gmail.com>
  • Loading branch information
zhaojh329 committed Aug 20, 2021
1 parent 21bd2ca commit 89c290c
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 46 deletions.
3 changes: 2 additions & 1 deletion example/test_plugin.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ static void test_handler(struct uh_connection *conn, int event)
}

struct uh_plugin_handler uh_plugin_handler = {
.path = "/test",
.path = "^/test$",
.wildcard = true,
.handler = test_handler
};
96 changes: 57 additions & 39 deletions src/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -453,59 +453,79 @@ static int on_header_value_cb(struct http_parser *parser, const char *at, size_t
return 0;
}

static bool set_path_handler(struct uh_connection_internal *conn, struct uh_path_handler *h,
struct uh_str *path, bool wildcard)
static bool match_path(struct uh_str *path, const char *needle, int needlelen, uint8_t flags, bool wildcard)
{
while (h) {
if (wildcard) {
int match = 0;
if (wildcard) {
int match = 0;

if (!(h->flags & UH_PATH_WILDCARD))
goto next;
if (!(flags & UH_PATH_WILDCARD))
return false;

if (path->len < h->len)
goto next;
if (path->len < needlelen)
return false;

if (h->flags & UH_PATH_MATCH_START) {
if (strncmp(path->p, h->path, h->len))
goto next;
match++;
}
if (flags & UH_PATH_MATCH_START) {
if (strncmp(path->p, needle, needlelen))
return false;
match++;
}

if (h->flags & UH_PATH_MATCH_END) {
if (strncmp(path->p + (path->len - h->len), h->path, h->len))
goto next;
match++;
}
if (flags & UH_PATH_MATCH_END) {
if (strncmp(path->p + (path->len - needlelen), needle, needlelen))
return false;
match++;
}

if (!match && !memmem(path->p, path->len, needle, needlelen))
return false;

return true;
} else {
if (flags & UH_PATH_WILDCARD)
return false;

if (!match && !memmem(path->p, path->len, h->path, h->len))
goto next;
if (needlelen != path->len || strncmp(path->p, needle, path->len))
return false;

return true;
}
}

static bool set_path_handler(struct uh_connection_internal *conn, struct uh_path_handler *h,
struct uh_str *path, bool wildcard)
{
while (h) {
if (match_path(path, h->path, h->len, h->flags, wildcard)) {
conn->handler = h->handler;
return true;
} else {
if (h->flags & UH_PATH_WILDCARD)
goto next;

if (h->len == path->len && !strncmp(path->p, h->path, path->len)) {
conn->handler = h->handler;
return true;
}
}

next:
h = h->next;
}

return false;
}

static bool set_plugin_handler(struct uh_connection_internal *conn, struct uh_plugin *p,
struct uh_str *path, bool wildcard)
{
while (p) {
if (match_path(path, p->path, p->len, p->flags, wildcard)) {
conn->handler = p->h->handler;
return true;
}

p = p->next;
}

return false;
}

static int on_headers_complete(struct http_parser *parser)
{
struct uh_connection_internal *conn = (struct uh_connection_internal *)parser->data;
struct uh_server_internal *srv = conn->srv;
struct uh_request *req = &conn->req;
struct uh_plugin *p = srv->plugins;
struct uh_str path;

http_parser_parse_url(O2D(conn, req->url.offset), req->url.length, false, &conn->url_parser);
Expand All @@ -520,14 +540,12 @@ static int on_headers_complete(struct http_parser *parser)
if (set_path_handler(conn, srv->handlers, &path, true))
goto done;

/* match plugin */
while (p) {
if (p->len == path.len && !strncmp(path.p, p->h->path, path.len)) {
conn->handler = p->h->handler;
goto done;
}
p = p->next;
}
/* match non wildcard plugin */
if (set_plugin_handler(conn, srv->plugins, &path, false))
goto done;

/* match wildcard plugin */
set_plugin_handler(conn, srv->plugins, &path, true);

done:
if (!conn->handler)
Expand Down
16 changes: 16 additions & 0 deletions src/uhttpd.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,24 @@ static int uh_load_plugin(struct uh_server *srv, const char *path)

p->h = h;
p->dlh = dlh;
p->path = h->path;
p->len = strlen(h->path);

if (h->wildcard) {
p->flags |= UH_PATH_WILDCARD;

if (h->path[0] == '^') {
p->flags |= UH_PATH_MATCH_START;
p->len--;
p->path++;
}

if (p->path[p->len - 1] == '$') {
p->flags |= UH_PATH_MATCH_END;
p->len--;
}
}

if (!srvi->plugins) {
srvi->plugins = p;
return 0;
Expand Down
15 changes: 9 additions & 6 deletions src/uhttpd.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,24 +120,27 @@ struct uh_server {
int (*set_index_page)(struct uh_server *srv, const char *name);
};

enum {
UH_PATH_WILDCARD = (1 << 0),
UH_PATH_MATCH_START = (1 << 1),
UH_PATH_MATCH_END = (1 << 2)
};

struct uh_plugin_handler {
const char *path;
bool wildcard;
uh_path_handler_prototype handler;
};

struct uh_plugin {
struct uh_plugin_handler *h;
void *dlh;
uint8_t flags;
uint8_t len;
const char *path;
struct uh_plugin *next;
};

enum {
UH_PATH_WILDCARD = (1 << 0),
UH_PATH_MATCH_START = (1 << 1),
UH_PATH_MATCH_END = (1 << 2)
};

struct uh_path_handler {
uh_path_handler_prototype handler;
struct uh_path_handler *next;
Expand Down

0 comments on commit 89c290c

Please sign in to comment.