support plugin

Signed-off-by: Jianhui Zhao <zhaojh329@gmail.com>
main
Jianhui Zhao 2020-03-14 00:23:37 +08:00
parent c40fcccd95
commit 5f4f6e0d97
9 changed files with 123 additions and 5 deletions

View File

@ -29,6 +29,7 @@ A Lightweight and fully asynchronous HTTP server library based on [libev] and [h
* Lightweight and fully asynchronous * Lightweight and fully asynchronous
* Use [libev] as its event backend * Use [libev] as its event backend
* Support HTTPS - OpenSSL, mbedtls and CyaSSl(wolfssl) * Support HTTPS - OpenSSL, mbedtls and CyaSSl(wolfssl)
* Support plugin
* Flexible - you can easily extend your application to have HTTP/HTTPS services * Flexible - you can easily extend your application to have HTTP/HTTPS services
* Code structure is concise and understandable, also suitable for learning * Code structure is concise and understandable, also suitable for learning

View File

@ -29,6 +29,7 @@
* 轻量、全异步 * 轻量、全异步
* 使用[libev]作为其事件后端 * 使用[libev]作为其事件后端
* 支持HTTPS - OpenSSL, mbedtls 和 CyaSSl(wolfssl) * 支持HTTPS - OpenSSL, mbedtls 和 CyaSSl(wolfssl)
* 支持插件
* 可伸缩 - 你可以非常方便的扩展你的应用程序使之具备HTTP/HTTPS服务 * 可伸缩 - 你可以非常方便的扩展你的应用程序使之具备HTTP/HTTPS服务
* 代码结构简洁通俗易懂,亦适合学习 * 代码结构简洁通俗易懂,亦适合学习

View File

@ -102,6 +102,8 @@ int main(int argc, char **argv)
srv->on_request = on_request; srv->on_request = on_request;
srv->load_plugin(srv, "/usr/local/lib/uhttpd/test.so");
uh_log_info("Listen on: *:%d\n", port); uh_log_info("Listen on: *:%d\n", port);
ev_signal_init(&signal_watcher, signal_cb, SIGINT); ev_signal_init(&signal_watcher, signal_cb, SIGINT);

View File

@ -97,6 +97,8 @@ target_link_libraries(uhttpd_s ${EXTRA_LIBS})
# configure a header file to pass some of the CMake settings to the source code # configure a header file to pass some of the CMake settings to the source code
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
add_subdirectory(plugins)
install( install(
FILES FILES
uhttpd.h uhttpd.h

View File

@ -252,16 +252,32 @@ static int on_body_cb(struct http_parser *parser, const char *at, size_t length)
return 0; return 0;
} }
static bool run_plugins(struct uh_connection *conn)
{
struct uh_plugin *p = conn->srv->plugins;
while (p) {
if (!strcmp(conn->get_url(conn), p->path)) {
p->handler(conn);
return true;
}
p = p->next;
}
return false;
}
static int on_message_complete_cb(struct http_parser *parser) static int on_message_complete_cb(struct http_parser *parser)
{ {
struct uh_connection *conn = (struct uh_connection *)parser->data; struct uh_connection *conn = (struct uh_connection *)parser->data;
struct uh_request *req = &conn->req; struct uh_request *req = &conn->req;
int i; int i;
if (!run_plugins(conn)) {
if (conn->srv->on_request) if (conn->srv->on_request)
conn->srv->on_request(conn); conn->srv->on_request(conn);
else else
conn_error(conn, 404, NULL); conn_error(conn, 404, NULL);
}
buffer_pull(&conn->rb, NULL, buffer_length(&conn->rb)); buffer_pull(&conn->rb, NULL, buffer_length(&conn->rb));

View File

@ -0,0 +1,14 @@
option(BUILD_TEST_PLUGIN "Build test plugin" ON)
set(PLUGINS "")
if(BUILD_TEST_PLUGIN)
set(PLUGINS ${PLUGINS} test_plugin)
add_library(test_plugin MODULE test.c)
set_target_properties(test_plugin PROPERTIES OUTPUT_NAME test PREFIX "")
endif()
install(
TARGETS ${PLUGINS}
LIBRARY DESTINATION lib/uhttpd
)

37
src/plugins/test.c 100644
View File

@ -0,0 +1,37 @@
/*
* MIT License
*
* Copyright (c) 2019 Jianhui Zhao <zhaojh329@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "uhttpd.h"
static void test_handler(struct uh_connection *conn)
{
conn->send_head(conn, 200, -1, NULL);
conn->chunk_printf(conn, "Url: %s\n", conn->get_url(conn));
conn->chunk_end(conn);
}
struct uh_plugin uh_plugin = {
.path = "/test",
.handler = test_handler
};

View File

@ -26,7 +26,7 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <dlfcn.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <sys/socket.h> #include <sys/socket.h>
@ -111,6 +111,40 @@ static int uh_server_ssl_init(struct uh_server *srv, const char *cert, const cha
} }
#endif #endif
static int uh_load_plugin(struct uh_server *srv, const char *path)
{
struct uh_plugin *p;
void *dlh;
dlh = dlopen(path, RTLD_LAZY | RTLD_LOCAL);
if (!dlh) {
uh_log_err("dlopen fail: %s\n", dlerror());
return -1;
}
p = dlsym(dlh, "uh_plugin");
if (!p) {
uh_log_err("not found symbol 'uh_plugin'\n");
return -1;
}
if (!p->path || !p->path[0] || !p->handler) {
uh_log_err("invalid plugin\n");
return -1;
}
if (!srv->plugins) {
srv->plugins = p;
return 0;
}
p->next = srv->plugins;
srv->plugins->prev = p;
srv->plugins = p;
return 0;
}
int uh_server_init(struct uh_server *srv, struct ev_loop *loop, const char *host, int port) int uh_server_init(struct uh_server *srv, struct ev_loop *loop, const char *host, int port)
{ {
struct sockaddr_in addr = { struct sockaddr_in addr = {
@ -150,6 +184,8 @@ int uh_server_init(struct uh_server *srv, struct ev_loop *loop, const char *host
srv->ssl_init = uh_server_ssl_init; srv->ssl_init = uh_server_ssl_init;
#endif #endif
srv->load_plugin = uh_load_plugin;
ev_io_init(&srv->ior, uh_accept_cb, sock, EV_READ); ev_io_init(&srv->ior, uh_accept_cb, sock, EV_READ);
ev_io_start(srv->loop, &srv->ior); ev_io_start(srv->loop, &srv->ior);

View File

@ -31,6 +31,13 @@
#include "config.h" #include "config.h"
#include "log.h" #include "log.h"
struct uh_plugin {
const char *path;
void (*handler)(struct uh_connection *conn);
struct uh_plugin *prev;
struct uh_plugin *next;
};
struct uh_server { struct uh_server {
int sock; int sock;
struct ev_loop *loop; struct ev_loop *loop;
@ -42,6 +49,8 @@ struct uh_server {
void *ssl_ctx; void *ssl_ctx;
int (*ssl_init)(struct uh_server *srv, const char *cert, const char *key); int (*ssl_init)(struct uh_server *srv, const char *cert, const char *key);
#endif #endif
struct uh_plugin *plugins;
int (*load_plugin)(struct uh_server *srv, const char *path);
}; };
/* /*