New member function for struct uh_client

cl->get_url(cl);
cl->get_var(cl, "name");

Signed-off-by: Jianhui Zhao <jianhuizhao329@gmail.com>
main
Jianhui Zhao 2018-01-01 11:44:46 +08:00
parent 89851e3f33
commit cbe7173205
6 changed files with 69 additions and 21 deletions

View File

@ -73,8 +73,10 @@ static void hello_action(struct uh_client *cl)
cl->chunk_printf(cl, "<h1>Hello Libuhttpd %s</h1>", UHTTPD_VERSION_STRING); cl->chunk_printf(cl, "<h1>Hello Libuhttpd %s</h1>", UHTTPD_VERSION_STRING);
cl->chunk_printf(cl, "<h1>REMOTE_ADDR: %s</h1>", cl->get_peer_addr(cl)); cl->chunk_printf(cl, "<h1>REMOTE_ADDR: %s</h1>", cl->get_peer_addr(cl));
cl->chunk_printf(cl, "<h1>URL: %s</h1>", cl->get_url(cl));
cl->chunk_printf(cl, "<h1>PATH: %s</h1>", cl->get_path(cl)); cl->chunk_printf(cl, "<h1>PATH: %s</h1>", cl->get_path(cl));
cl->chunk_printf(cl, "<h1>QUERY: %s</h1>", cl->get_query(cl)); cl->chunk_printf(cl, "<h1>QUERY: %s</h1>", cl->get_query(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->chunk_printf(cl, "<h1>BODY:%s</h1>", cl->get_body(cl, &body_len));
cl->request_done(cl); cl->request_done(cl);
} }

View File

@ -74,8 +74,10 @@ static void hello_action(struct uh_client *cl)
cl->chunk_printf(cl, "<h1>Hello Libuhttpd %s</h1>", UHTTPD_VERSION_STRING); cl->chunk_printf(cl, "<h1>Hello Libuhttpd %s</h1>", UHTTPD_VERSION_STRING);
cl->chunk_printf(cl, "<h1>REMOTE_ADDR: %s</h1>", cl->get_peer_addr(cl)); cl->chunk_printf(cl, "<h1>REMOTE_ADDR: %s</h1>", cl->get_peer_addr(cl));
cl->chunk_printf(cl, "<h1>URL: %s</h1>", cl->get_url(cl));
cl->chunk_printf(cl, "<h1>PATH: %s</h1>", cl->get_path(cl)); cl->chunk_printf(cl, "<h1>PATH: %s</h1>", cl->get_path(cl));
cl->chunk_printf(cl, "<h1>QUERY: %s</h1>", cl->get_query(cl)); cl->chunk_printf(cl, "<h1>QUERY: %s</h1>", cl->get_query(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->chunk_printf(cl, "<h1>BODY:%s</h1>", cl->get_body(cl, &body_len));
cl->request_done(cl); cl->request_done(cl);
} }

View File

@ -29,8 +29,10 @@ static void hello_action(struct uh_client *cl)
cl->chunk_printf(cl, "<h1>Hello Libuhttpd %s</h1>", UHTTPD_VERSION_STRING); cl->chunk_printf(cl, "<h1>Hello Libuhttpd %s</h1>", UHTTPD_VERSION_STRING);
cl->chunk_printf(cl, "<h1>REMOTE_ADDR: %s</h1>", cl->get_peer_addr(cl)); cl->chunk_printf(cl, "<h1>REMOTE_ADDR: %s</h1>", cl->get_peer_addr(cl));
cl->chunk_printf(cl, "<h1>URL: %s</h1>", cl->get_url(cl));
cl->chunk_printf(cl, "<h1>PATH: %s</h1>", cl->get_path(cl)); cl->chunk_printf(cl, "<h1>PATH: %s</h1>", cl->get_path(cl));
cl->chunk_printf(cl, "<h1>QUERY: %s</h1>", cl->get_query(cl)); cl->chunk_printf(cl, "<h1>QUERY: %s</h1>", cl->get_query(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->chunk_printf(cl, "<h1>BODY:%s</h1>", cl->get_body(cl, &body_len));
cl->request_done(cl); cl->request_done(cl);
} }

View File

@ -102,19 +102,29 @@ static inline const char *client_get_peer_addr(struct uh_client *cl)
return inet_ntoa(cl->peer_addr.sin_addr); return inet_ntoa(cl->peer_addr.sin_addr);
} }
static inline const char *client_get_url(struct uh_client *cl)
{
return kvlist_get(&cl->request.url, "url");
}
static inline const char *client_get_path(struct uh_client *cl) static inline const char *client_get_path(struct uh_client *cl)
{ {
return kvlist_get(&cl->request.hdr, "path"); return kvlist_get(&cl->request.url, "path");
} }
static inline const char *client_get_query(struct uh_client *cl) static inline const char *client_get_query(struct uh_client *cl)
{ {
return kvlist_get(&cl->request.hdr, "query"); return kvlist_get(&cl->request.url, "query");
}
const char *client_get_var(struct uh_client *cl, const char *name)
{
return kvlist_get(&cl->request.var, name);
} }
static inline const char *client_get_header(struct uh_client *cl, const char *name) static inline const char *client_get_header(struct uh_client *cl, const char *name)
{ {
return kvlist_get(&cl->request.hdr, name); return kvlist_get(&cl->request.header, name);
} }
static inline const char *client_get_body(struct uh_client *cl, int *len) static inline const char *client_get_body(struct uh_client *cl, int *len)
@ -125,13 +135,7 @@ static inline const char *client_get_body(struct uh_client *cl, int *len)
static void uh_handle_request(struct uh_client *cl) static void uh_handle_request(struct uh_client *cl)
{ {
char *path = kvlist_get(&cl->request.hdr, "path"); char *path = kvlist_get(&cl->request.url, "path");
#if (UHTTPD_DEBUG)
const char *name, *value;
kvlist_for_each(&cl->request.hdr, name, value) {
uh_log_debug("%s: %s", name, value);
}
#endif
if (handle_action_request(cl, path)) if (handle_action_request(cl, path))
return; return;
@ -188,7 +192,9 @@ static void client_request_done(struct uh_client *cl)
memset(&cl->request, 0, sizeof(cl->request)); memset(&cl->request, 0, sizeof(cl->request));
memset(&cl->dispatch, 0, sizeof(cl->dispatch)); memset(&cl->dispatch, 0, sizeof(cl->dispatch));
kvlist_init(&cl->request.hdr, hdr_get_len); kvlist_init(&cl->request.url, hdr_get_len);
kvlist_init(&cl->request.var, hdr_get_len);
kvlist_init(&cl->request.header, hdr_get_len);
uloop_timeout_set(&cl->timeout, UHTTPD_CONNECTION_TIMEOUT * 1000); uloop_timeout_set(&cl->timeout, UHTTPD_CONNECTION_TIMEOUT * 1000);
} }
@ -203,7 +209,9 @@ static void client_free(struct uh_client *cl)
shutdown(cl->sfd.fd.fd, SHUT_RDWR); shutdown(cl->sfd.fd.fd, SHUT_RDWR);
close(cl->sfd.fd.fd); close(cl->sfd.fd.fd);
list_del(&cl->list); list_del(&cl->list);
kvlist_free(&cl->request.hdr); kvlist_free(&cl->request.url);
kvlist_free(&cl->request.var);
kvlist_free(&cl->request.header);
cl->srv->nclients--; cl->srv->nclients--;
uh_log_debug("client_free: %s:%d", inet_ntoa(cl->peer_addr.sin_addr), cl->peer_addr.sin_port); uh_log_debug("client_free: %s:%d", inet_ntoa(cl->peer_addr.sin_addr), cl->peer_addr.sin_port);
@ -211,6 +219,26 @@ static void client_free(struct uh_client *cl)
} }
} }
static void parse_var(struct uh_client *cl, char *query)
{
struct kvlist *kv = &cl->request.var;
char *k, *v;
while (query && *query) {
k = query;
query = strchr(query, '&');
if (query)
*query++ = 0;
v = strchr(k, '=');
if (v)
*v++ = 0;
if (*k && v)
kvlist_set(kv, k, v);
}
}
static int client_parse_request(struct uh_client *cl, char *data) static int client_parse_request(struct uh_client *cl, char *data)
{ {
struct http_request *req = &cl->request; struct http_request *req = &cl->request;
@ -231,23 +259,29 @@ static int client_parse_request(struct uh_client *cl, char *data)
return CLIENT_STATE_DONE; return CLIENT_STATE_DONE;
} }
kvlist_set(&req->url, "url", url);
p = strchr(url, '?'); p = strchr(url, '?');
if (p) { if (p) {
*p = 0; *p = 0;
if (p[1]) if (p[1]) {
kvlist_set(&cl->request.hdr, "query", p + 1); kvlist_set(&req->url, "query", p + 1);
parse_var(cl, p + 1);
}
} }
if (uh_urldecode(path, sizeof(path) - 1, url, strlen(url)) < 0) if (uh_urldecode(path, sizeof(path) - 1, url, strlen(url)) < 0)
return CLIENT_STATE_DONE; return CLIENT_STATE_DONE;
kvlist_set(&cl->request.hdr, "path", path); kvlist_set(&req->url, "path", path);
req->method = h_method; req->method = h_method;
req->version = h_version; req->version = h_version;
if (req->version < UH_HTTP_VER_1_1) if (req->version < UH_HTTP_VER_1_1)
cl->connection_close = true; cl->connection_close = true;
uh_log_debug("http path: %s", kvlist_get(&req->url, "path"));
uh_log_debug("http query: %s", kvlist_get(&req->url, "query"));
uh_log_debug("http method: %s", http_methods[h_method]); uh_log_debug("http method: %s", http_methods[h_method]);
uh_log_debug("http version: %s", http_versions[h_version]); uh_log_debug("http version: %s", http_versions[h_version]);
@ -324,7 +358,7 @@ static inline bool client_data_cb(struct uh_client *cl, char *buf, int len)
static void client_parse_header(struct uh_client *cl, char *data) static void client_parse_header(struct uh_client *cl, char *data)
{ {
struct http_request *r = &cl->request; struct http_request *req = &cl->request;
char *err; char *err;
char *name; char *name;
char *val; char *val;
@ -347,7 +381,7 @@ static void client_parse_header(struct uh_client *cl, char *data)
*name = tolower(*name); *name = tolower(*name);
if (!strcmp(data, "content-length")) { if (!strcmp(data, "content-length")) {
r->content_length = strtoul(val, &err, 0); req->content_length = strtoul(val, &err, 0);
if (err && *err) { if (err && *err) {
cl->send_error(cl, 400, "Bad Request", "Invalid Content-Length"); cl->send_error(cl, 400, "Bad Request", "Invalid Content-Length");
return; return;
@ -359,7 +393,7 @@ static void client_parse_header(struct uh_client *cl, char *data)
cl->connection_close = true; cl->connection_close = true;
} }
kvlist_set(&cl->request.hdr, data, val); kvlist_set(&req->header, data, val);
cl->state = CLIENT_STATE_HEADER; cl->state = CLIENT_STATE_HEADER;
} }
@ -486,7 +520,9 @@ void uh_accept_client(struct uh_server *srv, bool ssl)
uloop_timeout_set(&cl->timeout, UHTTPD_CONNECTION_TIMEOUT * 1000); uloop_timeout_set(&cl->timeout, UHTTPD_CONNECTION_TIMEOUT * 1000);
list_add(&cl->list, &srv->clients); list_add(&cl->list, &srv->clients);
kvlist_init(&cl->request.hdr, hdr_get_len); kvlist_init(&cl->request.url, hdr_get_len);
kvlist_init(&cl->request.var, hdr_get_len);
kvlist_init(&cl->request.header, hdr_get_len);
cl->srv = srv; cl->srv = srv;
cl->srv->nclients++; cl->srv->nclients++;
@ -507,8 +543,10 @@ void uh_accept_client(struct uh_server *srv, bool ssl)
cl->chunk_vprintf = uh_chunk_vprintf; cl->chunk_vprintf = uh_chunk_vprintf;
cl->get_peer_addr = client_get_peer_addr; cl->get_peer_addr = client_get_peer_addr;
cl->get_url = client_get_url;
cl->get_path = client_get_path; cl->get_path = client_get_path;
cl->get_query = client_get_query; cl->get_query = client_get_query;
cl->get_var = client_get_var;
cl->get_header = client_get_header; cl->get_header = client_get_header;
cl->get_body = client_get_body; cl->get_body = client_get_body;

View File

@ -50,7 +50,9 @@ struct http_request {
enum http_method method; enum http_method method;
enum http_version version; enum http_version version;
int content_length; int content_length;
struct kvlist hdr; struct kvlist url;
struct kvlist var;
struct kvlist header;
}; };
struct uh_client; struct uh_client;
@ -106,8 +108,10 @@ struct uh_client {
void (*chunk_vprintf)(struct uh_client *cl, const char *format, va_list arg); void (*chunk_vprintf)(struct uh_client *cl, const char *format, va_list arg);
const char *(*get_peer_addr)(struct uh_client *cl); const char *(*get_peer_addr)(struct uh_client *cl);
const char *(*get_url)(struct uh_client *cl);
const char *(*get_path)(struct uh_client *cl); const char *(*get_path)(struct uh_client *cl);
const char *(*get_query)(struct uh_client *cl); const char *(*get_query)(struct uh_client *cl);
const char *(*get_var)(struct uh_client *cl, const char *name);
const char *(*get_header)(struct uh_client *cl, const char *name); const char *(*get_header)(struct uh_client *cl, const char *name);
const char *(*get_body)(struct uh_client *cl, int *len); const char *(*get_body)(struct uh_client *cl, int *len);
}; };

View File

@ -296,7 +296,7 @@ static void uh_file_response_200(struct uh_client *cl, struct stat *s)
static int uh_file_if_modified_since(struct uh_client *cl, struct stat *s) static int uh_file_if_modified_since(struct uh_client *cl, struct stat *s)
{ {
const char *date = kvlist_get(&cl->request.hdr, "if-modified-since"); const char *date = kvlist_get(&cl->request.header, "if-modified-since");
struct tm t; struct tm t;
if (!date) if (!date)