parent
abd7dbb17a
commit
3b1d425d07
|
@ -21,12 +21,17 @@
|
|||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <uhttpd.h>
|
||||
#include <string.h>
|
||||
#include <libubox/ulog.h>
|
||||
|
||||
static void hello_action(struct uh_client *cl)
|
||||
static int on_request(struct uh_client *cl)
|
||||
{
|
||||
const char *path = cl->get_path(cl);
|
||||
int body_len = 0;
|
||||
|
||||
if (strcmp(path, "/hello"))
|
||||
return UH_REQUEST_CONTINUE;
|
||||
|
||||
cl->send_header(cl, 200, "OK", -1);
|
||||
cl->append_header(cl, "Myheader", "Hello");
|
||||
cl->header_end(cl);
|
||||
|
@ -39,6 +44,8 @@ static void hello_action(struct uh_client *cl)
|
|||
cl->chunk_printf(cl, "<h1>VAR name: %s</h1>", cl->get_var(cl, "name"));
|
||||
cl->chunk_printf(cl, "<h1>BODY:%s</h1>", cl->get_body(cl, &body_len));
|
||||
cl->request_done(cl);
|
||||
|
||||
return UH_REQUEST_DONE;
|
||||
}
|
||||
|
||||
static void usage(const char *prog)
|
||||
|
@ -96,7 +103,7 @@ int main(int argc, char **argv)
|
|||
|
||||
ULOG_INFO("Listen on: %s *:%d\n", srv->ssl ? "https" : "http", port);
|
||||
|
||||
srv->add_action(srv, "/hello", hello_action);
|
||||
srv->request_cb = on_request;
|
||||
|
||||
uloop_run();
|
||||
done:
|
||||
|
|
|
@ -51,7 +51,11 @@ srv:set_error404_cb(function(cl, opt)
|
|||
uh.request_done(cl)
|
||||
end)
|
||||
|
||||
srv:add_action("/lua", function(cl, opt)
|
||||
srv:set_request_cb(function(cl, opt)
|
||||
if opt.path ~= "/hello" then
|
||||
return uh.REQUEST_CONTINUE
|
||||
end
|
||||
|
||||
uh.send_header(cl, 200, "OK", -1)
|
||||
uh.append_header(cl, "Myheader", "Hello")
|
||||
uh.header_end(cl)
|
||||
|
@ -74,6 +78,8 @@ srv:add_action("/lua", function(cl, opt)
|
|||
end
|
||||
|
||||
uh.request_done(cl)
|
||||
|
||||
return uh.REQUEST_DONE
|
||||
end)
|
||||
|
||||
uloop.run()
|
||||
|
|
|
@ -21,10 +21,16 @@
|
|||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <uhttpd.h>
|
||||
#include <string.h>
|
||||
#include <libubox/ulog.h>
|
||||
|
||||
static void hello_action(struct uh_client *cl)
|
||||
static int on_request(struct uh_client *cl)
|
||||
{
|
||||
const char *path = cl->get_path(cl);
|
||||
|
||||
if (strcmp(path, "/template.html"))
|
||||
return UH_REQUEST_CONTINUE;
|
||||
|
||||
#if (UHTTPD_LUA_SUPPORT)
|
||||
uh_template(cl);
|
||||
#else
|
||||
|
@ -34,6 +40,8 @@ static void hello_action(struct uh_client *cl)
|
|||
cl->chunk_printf(cl, "<h1>Lua not enabled when compile</h1>");
|
||||
cl->request_done(cl);
|
||||
#endif
|
||||
|
||||
return UH_REQUEST_DONE;
|
||||
}
|
||||
|
||||
static void usage(const char *prog)
|
||||
|
@ -72,7 +80,7 @@ int main(int argc, char **argv)
|
|||
|
||||
if (!verbose)
|
||||
ulog_threshold(LOG_ERR);
|
||||
|
||||
|
||||
ULOG_INFO("libuhttpd version: %s\n", UHTTPD_VERSION_STRING);
|
||||
|
||||
uloop_init();
|
||||
|
@ -91,12 +99,16 @@ int main(int argc, char **argv)
|
|||
|
||||
ULOG_INFO("Listen on: %s *:%d\n", srv->ssl ? "https" : "http", port);
|
||||
|
||||
srv->add_action(srv, "/template.html", hello_action);
|
||||
|
||||
srv->request_cb = on_request;
|
||||
|
||||
uloop_run();
|
||||
done:
|
||||
uloop_done();
|
||||
srv->free(srv);
|
||||
|
||||
|
||||
if (srv) {
|
||||
srv->free(srv);
|
||||
free(srv);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ find_package(Lua)
|
|||
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${LIBUBOX_INCLUDE_DIR})
|
||||
|
||||
set(EXTRA_LIBS ${LIBUBOX_LIBRARY} dl)
|
||||
set(SOURCE_FILES uhttpd.c client.c log.c utils.c file.c action.c)
|
||||
set(SOURCE_FILES uhttpd.c client.c log.c utils.c file.c)
|
||||
|
||||
set(UHTTPD_SSL_SUPPORT_CONFIG 1)
|
||||
option(UHTTPD_SSL_SUPPORT "SSL support" ON)
|
||||
|
@ -60,7 +60,6 @@ install(
|
|||
${CMAKE_CURRENT_BINARY_DIR}/config.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/uhttpd.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/client.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/action.h
|
||||
DESTINATION
|
||||
include/uhttpd
|
||||
)
|
||||
|
|
128
src/action.c
128
src/action.c
|
@ -1,128 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2017 Jianhui Zhao <jianhuizhao329@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "action.h"
|
||||
#include "uhttpd.h"
|
||||
#include "log.h"
|
||||
|
||||
#define UH_ACTION_DATA_BUF_SIZE 1024
|
||||
#define UH_ACTION_MAX_POST_SIZE 4096
|
||||
|
||||
int uh_add_action(struct uh_server *srv, const char *path, action_cb_t cb)
|
||||
{
|
||||
struct uh_action *a;
|
||||
|
||||
a = calloc(1, sizeof(struct uh_action) + strlen(path) + 1);
|
||||
if (!a) {
|
||||
uh_log_err("calloc");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strlen(path) > sizeof(a->path) - 1) {
|
||||
uh_log_err("The given path is too long");
|
||||
goto err;
|
||||
}
|
||||
|
||||
a->avl.key = strcpy(a->path, path);
|
||||
a->cb = cb;
|
||||
avl_insert(&srv->actions, &a->avl);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
free(a);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int action_data_send(struct uh_client *cl, const char *data, int len)
|
||||
{
|
||||
struct dispatch *d = &cl->dispatch;
|
||||
d->action.post_len += len;
|
||||
|
||||
if (d->action.post_len > UH_ACTION_MAX_POST_SIZE)
|
||||
goto err;
|
||||
|
||||
if (d->action.post_len > UH_ACTION_DATA_BUF_SIZE) {
|
||||
d->action.body = realloc(d->action.body, UH_ACTION_MAX_POST_SIZE);
|
||||
if (!d->action.body) {
|
||||
cl->send_error(cl, 500, "Internal Server Error", "No memory");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(d->action.body, data, len);
|
||||
return len;
|
||||
err:
|
||||
cl->send_error(cl, 413, "Request Entity Too Large", NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void action_data_done(struct uh_client *cl)
|
||||
{
|
||||
struct uh_action *a = cl->dispatch.action.a;
|
||||
a->cb(cl);
|
||||
}
|
||||
|
||||
static void action_data_free(struct uh_client *cl)
|
||||
{
|
||||
struct dispatch *d = &cl->dispatch;
|
||||
free(d->action.body);
|
||||
}
|
||||
|
||||
bool handle_action_request(struct uh_client *cl, const char *path)
|
||||
{
|
||||
struct dispatch *d = &cl->dispatch;
|
||||
struct uh_action *a;
|
||||
|
||||
a = avl_find_element(&cl->srv->actions, path, a, avl);
|
||||
if (a) {
|
||||
switch (cl->request.method) {
|
||||
case UH_HTTP_MSG_POST:
|
||||
d->action.a = a;
|
||||
d->data_send = action_data_send;
|
||||
d->data_done = action_data_done;
|
||||
d->free = action_data_free;
|
||||
d->action.body = calloc(1, UH_ACTION_DATA_BUF_SIZE);
|
||||
if (!d->action.body)
|
||||
cl->send_error(cl, 500, "Internal Server Error", "No memory");
|
||||
break;
|
||||
|
||||
case UH_HTTP_MSG_GET:
|
||||
a->cb(cl);
|
||||
break;
|
||||
|
||||
default:
|
||||
cl->send_error(cl, 400, "Bad Request", "Invalid Request");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return a ? true : false;
|
||||
}
|
||||
|
||||
|
||||
void uh_action_free(struct uh_server *srv)
|
||||
{
|
||||
struct uh_action *node, *tmp;
|
||||
|
||||
avl_remove_all_elements(&srv->actions, node, avl, tmp)
|
||||
free(node);
|
||||
}
|
39
src/action.h
39
src/action.h
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2017 Jianhui Zhao <jianhuizhao329@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef _ACTION_H
|
||||
#define _ACTION_H
|
||||
|
||||
#include "client.h"
|
||||
|
||||
typedef void (*action_cb_t)(struct uh_client *cl);
|
||||
|
||||
struct uh_action {
|
||||
struct avl_node avl;
|
||||
action_cb_t cb;
|
||||
char path[0];
|
||||
};
|
||||
|
||||
int uh_add_action(struct uh_server *srv, const char *path, action_cb_t cb);
|
||||
|
||||
bool handle_action_request(struct uh_client *cl, const char *path);
|
||||
|
||||
void uh_action_free(struct uh_server *srv);
|
||||
|
||||
#endif
|
86
src/client.c
86
src/client.c
|
@ -148,16 +148,82 @@ static inline const char *client_get_header(struct uh_client *cl, const char *na
|
|||
|
||||
static inline const char *client_get_body(struct uh_client *cl, int *len)
|
||||
{
|
||||
*len = cl->dispatch.action.post_len;
|
||||
return cl->dispatch.action.body;
|
||||
*len = cl->dispatch.post_len;
|
||||
return cl->dispatch.body;
|
||||
}
|
||||
|
||||
static int post_post_data(struct uh_client *cl, const char *data, int len)
|
||||
{
|
||||
struct dispatch *d = &cl->dispatch;
|
||||
d->post_len += len;
|
||||
|
||||
if (d->post_len > UH_POST_MAX_POST_SIZE)
|
||||
goto err;
|
||||
|
||||
if (d->post_len > UH_POST_DATA_BUF_SIZE) {
|
||||
d->body = realloc(d->body, UH_POST_MAX_POST_SIZE);
|
||||
if (!d->body) {
|
||||
cl->send_error(cl, 500, "Internal Server Error", "No memory");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(d->body, data, len);
|
||||
return len;
|
||||
err:
|
||||
cl->send_error(cl, 413, "Request Entity Too Large", NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void post_post_done(struct uh_client *cl)
|
||||
{
|
||||
char *path = kvlist_get(&cl->request.url, "path");
|
||||
|
||||
if (cl->srv->request_cb(cl) == UH_REQUEST_DONE)
|
||||
return;
|
||||
|
||||
if (handle_file_request(cl, path))
|
||||
return;
|
||||
|
||||
if (cl->srv->error404_cb) {
|
||||
cl->srv->error404_cb(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
cl->send_error(cl, 404, "Not Found", "The requested PATH %s was not found on this server.", path);
|
||||
}
|
||||
|
||||
static void post_data_free(struct uh_client *cl)
|
||||
{
|
||||
struct dispatch *d = &cl->dispatch;
|
||||
free(d->body);
|
||||
}
|
||||
|
||||
static void uh_handle_request(struct uh_client *cl)
|
||||
{
|
||||
char *path = kvlist_get(&cl->request.url, "path");
|
||||
|
||||
if (handle_action_request(cl, path))
|
||||
return;
|
||||
if (cl->srv->request_cb) {
|
||||
struct dispatch *d = &cl->dispatch;
|
||||
|
||||
switch (cl->request.method) {
|
||||
case UH_HTTP_MSG_GET:
|
||||
if (cl->srv->request_cb(cl) == UH_REQUEST_DONE)
|
||||
return;
|
||||
break;
|
||||
case UH_HTTP_MSG_POST:
|
||||
d->post_data = post_post_data;
|
||||
d->post_done = post_post_done;
|
||||
d->free = post_data_free;
|
||||
d->body = calloc(1, UH_POST_DATA_BUF_SIZE);
|
||||
if (!d->body)
|
||||
cl->send_error(cl, 500, "Internal Server Error", "No memory");
|
||||
return;
|
||||
default:
|
||||
cl->send_error(cl, 400, "Bad Request", "Invalid Request");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (handle_file_request(cl, path))
|
||||
return;
|
||||
|
@ -188,6 +254,8 @@ static void dispatch_done(struct uh_client *cl)
|
|||
{
|
||||
if (cl->dispatch.free)
|
||||
cl->dispatch.free(cl);
|
||||
|
||||
memset(&cl->dispatch, 0, sizeof(struct dispatch));
|
||||
}
|
||||
|
||||
static inline int hdr_get_len(struct kvlist *kv, const void *data)
|
||||
|
@ -340,13 +408,13 @@ static void client_poll_post_data(struct uh_client *cl)
|
|||
if (!buf || !len)
|
||||
break;
|
||||
|
||||
if (!d->data_send)
|
||||
if (!d->post_data)
|
||||
return;
|
||||
|
||||
cur_len = min(r->content_length, len);
|
||||
if (cur_len) {
|
||||
if (d->data_send)
|
||||
cur_len = d->data_send(cl, buf, cur_len);
|
||||
if (d->post_data)
|
||||
cur_len = d->post_data(cl, buf, cur_len);
|
||||
|
||||
r->content_length -= cur_len;
|
||||
ustream_consume(cl->us, cur_len);
|
||||
|
@ -355,8 +423,8 @@ static void client_poll_post_data(struct uh_client *cl)
|
|||
}
|
||||
|
||||
if (!r->content_length && cl->state != CLIENT_STATE_DONE) {
|
||||
if (cl->dispatch.data_done)
|
||||
cl->dispatch.data_done(cl);
|
||||
if (cl->dispatch.post_done)
|
||||
cl->dispatch.post_done(cl);
|
||||
|
||||
cl->state = CLIENT_STATE_DONE;
|
||||
}
|
||||
|
|
28
src/client.h
28
src/client.h
|
@ -32,6 +32,14 @@
|
|||
|
||||
#define UHTTPD_CONNECTION_TIMEOUT 30
|
||||
|
||||
#define UH_POST_DATA_BUF_SIZE 1024
|
||||
#define UH_POST_MAX_POST_SIZE 4096
|
||||
|
||||
enum request_status {
|
||||
UH_REQUEST_DONE,
|
||||
UH_REQUEST_CONTINUE
|
||||
};
|
||||
|
||||
enum http_method {
|
||||
UH_HTTP_MSG_GET,
|
||||
UH_HTTP_MSG_POST,
|
||||
|
@ -64,21 +72,17 @@ struct http_request {
|
|||
struct uh_client;
|
||||
|
||||
struct dispatch {
|
||||
int (*data_send)(struct uh_client *cl, const char *data, int len);
|
||||
void (*data_done)(struct uh_client *cl);
|
||||
int (*post_data)(struct uh_client *cl, const char *data, int len);
|
||||
void (*post_done)(struct uh_client *cl);
|
||||
void (*write_cb)(struct uh_client *cl);
|
||||
void (*free)(struct uh_client *cl);
|
||||
|
||||
union {
|
||||
struct {
|
||||
int fd;
|
||||
} file;
|
||||
struct {
|
||||
int post_len;
|
||||
char *body;
|
||||
struct uh_action *a;
|
||||
} action;
|
||||
};
|
||||
struct {
|
||||
int fd;
|
||||
} file;
|
||||
|
||||
int post_len;
|
||||
char *body;
|
||||
};
|
||||
|
||||
struct uh_client {
|
||||
|
|
|
@ -114,17 +114,20 @@ static void lua_prepare_action_argument(struct uh_client *cl, lua_State *L)
|
|||
add_all_header(cl, L);
|
||||
}
|
||||
|
||||
static void lua_uh_action(struct uh_client *cl)
|
||||
static int lua_uh_on_request(struct uh_client *cl)
|
||||
{
|
||||
struct uh_server *srv = cl->srv;
|
||||
lua_State *L = srv->L;
|
||||
struct lua_uh_server *lsrv = container_of(cl->srv, struct lua_uh_server, srv);
|
||||
lua_State *L = cl->srv->L;
|
||||
|
||||
lua_getglobal(L, "__uh_action_cb");
|
||||
lua_getfield(L, -1, cl->get_path(cl));
|
||||
lua_getglobal(L, "__uh_request_cb");
|
||||
lua_rawgeti(L, -1, lsrv->request_cb_ref);
|
||||
lua_remove(L, -2);
|
||||
|
||||
lua_prepare_action_argument(cl, L);
|
||||
|
||||
lua_call(L, 2, 0);
|
||||
lua_call(L, 2, 1);
|
||||
|
||||
return lua_tointeger(L, -1);
|
||||
}
|
||||
|
||||
static int lua_uh_ssl_init(lua_State *L)
|
||||
|
@ -144,18 +147,17 @@ static int lua_uh_ssl_init(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lua_uh_add_action(lua_State *L)
|
||||
static int lua_uh_set_request_cb(lua_State *L)
|
||||
{
|
||||
struct lua_uh_server *lsrv = luaL_checkudata(L, 1, LUA_UH_SERVER_MT);
|
||||
const char *path = luaL_checkstring(L, 2);
|
||||
|
||||
luaL_checktype(L, 3, LUA_TFUNCTION);
|
||||
luaL_checktype(L, 2, LUA_TFUNCTION);
|
||||
|
||||
lua_getglobal(L, "__uh_action_cb");
|
||||
lua_pushvalue(L, 3);
|
||||
lua_setfield(L, -2, path);
|
||||
lua_getglobal(L, "__uh_request_cb");
|
||||
lua_pushvalue(L, 2);
|
||||
lsrv->request_cb_ref = luaL_ref(L, -2);
|
||||
|
||||
lsrv->srv.add_action(&lsrv->srv, path, lua_uh_action);
|
||||
lsrv->srv.request_cb = lua_uh_on_request;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -220,7 +222,7 @@ static int lua_uh_server_free(lua_State *L)
|
|||
|
||||
static const luaL_Reg server_mt[] = {
|
||||
{ "ssl_init", lua_uh_ssl_init },
|
||||
{ "add_action", lua_uh_add_action },
|
||||
{ "set_request_cb", lua_uh_set_request_cb },
|
||||
{ "set_error404_cb", lua_uh_set_error404_cb },
|
||||
{ "set_options", lua_uh_set_options },
|
||||
{ "free", lua_uh_server_free },
|
||||
|
@ -374,7 +376,7 @@ static const luaL_Reg uhttpd_fun[] = {
|
|||
int luaopen_uhttpd(lua_State *L)
|
||||
{
|
||||
lua_newtable(L);
|
||||
lua_setglobal(L, "__uh_action_cb");
|
||||
lua_setglobal(L, "__uh_request_cb");
|
||||
|
||||
lua_newtable(L);
|
||||
lua_setglobal(L, "__uh_error404_cb");
|
||||
|
@ -401,5 +403,11 @@ int luaopen_uhttpd(lua_State *L)
|
|||
lua_pushinteger(L, LOG_ERR);
|
||||
lua_setfield(L, -2, "LOG_ERR");
|
||||
|
||||
lua_pushinteger(L, UH_REQUEST_DONE);
|
||||
lua_setfield(L, -2, "REQUEST_DONE");
|
||||
|
||||
lua_pushinteger(L, UH_REQUEST_CONTINUE);
|
||||
lua_setfield(L, -2, "REQUEST_CONTINUE");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
struct lua_uh_server {
|
||||
struct uh_server srv;
|
||||
int error404_cb_ref;
|
||||
int request_cb_ref;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -49,7 +49,6 @@ static void uh_server_free(struct uh_server *srv)
|
|||
list_for_each_entry_safe(cl, tmp, &srv->clients, list)
|
||||
cl->free(cl);
|
||||
|
||||
uh_action_free(srv);
|
||||
uh_ssl_free();
|
||||
free(srv->docroot);
|
||||
free(srv->index_file);
|
||||
|
@ -89,7 +88,6 @@ void uh_server_init(struct uh_server *srv, int sock)
|
|||
srv->free = uh_server_free;
|
||||
srv->set_docroot = uh_set_docroot;
|
||||
srv->set_index_file = uh_set_index_file;
|
||||
srv->add_action = uh_add_action;
|
||||
|
||||
#if (UHTTPD_SSL_SUPPORT)
|
||||
srv->ssl_init = uh_ssl_init;
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
|
||||
#include "config.h"
|
||||
#include "client.h"
|
||||
#include "action.h"
|
||||
|
||||
struct uh_server {
|
||||
bool ssl;
|
||||
|
@ -37,7 +36,7 @@ struct uh_server {
|
|||
void (*set_docroot)(struct uh_server *srv, const char *docroot);
|
||||
void (*set_index_file)(struct uh_server *srv, const char *index_file);
|
||||
void (*error404_cb)(struct uh_client *cl);
|
||||
int (*add_action)(struct uh_server *srv, const char *path, action_cb_t cb);
|
||||
int (*request_cb)(struct uh_client *cl);
|
||||
|
||||
#if (UHTTPD_SSL_SUPPORT)
|
||||
int (*ssl_init)(struct uh_server *srv, const char *key, const char *crt);
|
||||
|
|
Loading…
Reference in New Issue