parent
c40fcccd95
commit
5f4f6e0d97
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
* 轻量、全异步
|
* 轻量、全异步
|
||||||
* 使用[libev]作为其事件后端
|
* 使用[libev]作为其事件后端
|
||||||
* 支持HTTPS - OpenSSL, mbedtls 和 CyaSSl(wolfssl)
|
* 支持HTTPS - OpenSSL, mbedtls 和 CyaSSl(wolfssl)
|
||||||
|
* 支持插件
|
||||||
* 可伸缩 - 你可以非常方便的扩展你的应用程序,使之具备HTTP/HTTPS服务
|
* 可伸缩 - 你可以非常方便的扩展你的应用程序,使之具备HTTP/HTTPS服务
|
||||||
* 代码结构简洁通俗易懂,亦适合学习
|
* 代码结构简洁通俗易懂,亦适合学习
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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));
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
)
|
|
@ -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
|
||||||
|
};
|
38
src/uhttpd.c
38
src/uhttpd.c
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue