Skip to content

Commit

Permalink
Optimize code and fix gzip encoding
Browse files Browse the repository at this point in the history
Signed-off-by: zhaojh329 <zhaojh329@gmail.com>
  • Loading branch information
zhaojh329 committed Sep 7, 2020
1 parent 87a209c commit 28c8146
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 123 deletions.
14 changes: 8 additions & 6 deletions example/example.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,18 @@ static const char *index_page = "index.html";
static void on_request(struct uh_connection *conn)
{
if (!serve_file) {
int body_len;
const char *body = conn->get_body(conn, &body_len);
const struct uh_str path = conn->get_path(conn);
const struct uh_str query = conn->get_query(conn);
const struct uh_str ua = conn->get_header(conn, "User-Agent");
const struct uh_str body = conn->get_body(conn);

conn->send_head(conn, HTTP_STATUS_OK, -1, NULL);
conn->chunk_printf(conn, "I'm Libuhttpd: %s\n", UHTTPD_VERSION_STRING);
conn->chunk_printf(conn, "Method: %s\n", conn->get_method_str(conn));
conn->chunk_printf(conn, "Path: %s\n", conn->get_path(conn));
conn->chunk_printf(conn, "Query: %s\n", conn->get_query(conn));
conn->chunk_printf(conn, "User-Agent: %s\n", conn->get_header(conn, "User-Agent"));
conn->chunk_printf(conn, "Body: %.*s\n", body_len, body);
conn->chunk_printf(conn, "Path: %.*s\n", path.len ,path.p);
conn->chunk_printf(conn, "Query: %.*s\n", query.len, query.p);
conn->chunk_printf(conn, "User-Agent: %.*s\n", ua.len, ua.p);
conn->chunk_printf(conn, "Body: %.*s\n", body.len, body.p);
conn->chunk_end(conn);
} else {
conn->serve_file(conn, docroot, index_page);
Expand Down
113 changes: 41 additions & 72 deletions src/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,75 +169,58 @@ static const char *conn_get_method_str(struct uh_connection *conn)
return http_method_str(conn->parser.method);
}

/* offset of the request field */
#define ROF(c, a) (a - (const char *)c->rb.data)

/* data of the request field */
#define O2D(c, o) ((const char *)c->rb.data + o)

static const char *conn_get_path(struct uh_connection *conn)
static const struct uh_str conn_get_path(struct uh_connection *conn)
{
struct http_parser_url *u = &conn->url_parser;
struct uh_request *req = &conn->req;
struct uh_str path;

path.p = req->url.p + u->field_data[UF_PATH].off;
path.len = u->field_data[UF_PATH].len;

if (!req->url.path)
req->url.path = strndup(O2D(conn, u->field_data[UF_PATH].off) + req->url.offset, u->field_data[UF_PATH].len);
return req->url.path;
return path;
}

static const char *conn_get_query(struct uh_connection *conn)
static const struct uh_str conn_get_query(struct uh_connection *conn)
{
struct http_parser_url *u = &conn->url_parser;
struct uh_request *req = &conn->req;
struct uh_str query = {};

if (!(u->field_set & (1 << UF_QUERY)))
return "";
return query;

if (!req->url.query)
req->url.query = strndup(O2D(conn, u->field_data[UF_QUERY].off) + req->url.offset, u->field_data[UF_QUERY].len);
query.p = req->url.p + u->field_data[UF_QUERY].off;
query.len = u->field_data[UF_QUERY].len;

return req->url.query;
return query;
}

static const char *conn_get_header(struct uh_connection *conn, const char *name)
static const struct uh_str conn_get_header(struct uh_connection *conn, const char *name)
{
struct uh_request *req = &conn->req;
int name_len = strlen(name);
int i, j;
struct uh_str *field;
struct uh_str value = {};
int i;

for (i = 0; i < UHTTPD_MAX_HEADER_NUM; i++) {
if (!req->headers[i].name)
break;
if (!strcasecmp(req->headers[i].name, name))
return req->headers[i].value;
}
field = &req->headers[i].field;
if (!field->p)
return value;

if (i == UHTTPD_MAX_HEADER_NUM)
return NULL;

for (j = 0; j < UHTTPD_MAX_HEADER_NUM; j++) {
if (req->headers_info[j].name_offset > 0) {
const char *p = O2D(conn, req->headers_info[j].name_offset);
if (name_len == req->headers_info[j].name_len && !strncasecmp(p, name, req->headers_info[j].name_len)) {
req->headers[i].name = strndup(p, req->headers_info[j].name_len);
req->headers[i].value = strndup(O2D(conn, req->headers_info[j].value_offset), req->headers_info[j].value_len);
req->headers_info[j].name_len = 0;
return req->headers[i].value;
}
if (name_len == field->len && !strncasecmp(field->p, name, name_len)) {
value.p = req->headers[i].value.p;
value.len = req->headers[i].value.len;
}
}

return NULL;
return value;
}

static const char *conn_get_body(struct uh_connection *conn, int *len)
static const struct uh_str conn_get_body(struct uh_connection *conn)
{
struct uh_request *req = &conn->req;
const char *at = O2D(conn, req->body.offset);

*len = req->body.len;

return at;
return conn->req.body;
}

static int on_message_begin_cb(struct http_parser *parser)
Expand All @@ -247,20 +230,19 @@ static int on_message_begin_cb(struct http_parser *parser)

req->last_was_header_value = true;

http_parser_url_init(&conn->url_parser);

return 0;
}

static int on_url_cb(struct http_parser *parser, const char *at, size_t length)
{
struct uh_connection *conn = (struct uh_connection *)parser->data;
struct uh_request *req = &conn->req;
struct uh_str *url = &conn->req.url;

if (req->url.offset == 0) {
req->url.offset = ROF(conn, at);
http_parser_url_init(&conn->url_parser);
}

req->url.length += length;
if (!url->p)
url->p = at;
url->len += length;

return 0;
}
Expand All @@ -279,10 +261,10 @@ static int on_header_field_cb(struct http_parser *parser, const char *at, size_t
return 1;
}

req->headers_info[req->header_num - 1].name_offset = ROF(conn, at);
req->headers[req->header_num - 1].field.p = at;
}

req->headers_info[req->header_num - 1].name_len += length;
req->headers[req->header_num - 1].field.len += length;

return 0;
}
Expand All @@ -294,10 +276,10 @@ static int on_header_value_cb(struct http_parser *parser, const char *at, size_t

if (!req->last_was_header_value) {
req->last_was_header_value = true;
req->headers_info[req->header_num - 1].value_offset = ROF(conn, at);
req->headers[req->header_num - 1].value.p = at;
}

req->headers_info[req->header_num - 1].value_len += length;
req->headers[req->header_num - 1].value.len += length;

return 0;
}
Expand All @@ -307,8 +289,8 @@ static int on_body_cb(struct http_parser *parser, const char *at, size_t length)
struct uh_connection *conn = (struct uh_connection *)parser->data;
struct uh_request *req = &conn->req;

if (req->body.offset == 0)
req->body.offset = ROF(conn, at);
if (!req->body.p)
req->body.p = at;
req->body.len += length;

return 0;
Expand All @@ -317,9 +299,10 @@ static int on_body_cb(struct http_parser *parser, const char *at, size_t length)
static bool run_plugins(struct uh_connection *conn)
{
struct uh_plugin *p = conn->srv->plugins;
struct uh_str path = conn->get_path(conn);

while (p) {
if (!strcmp(conn->get_path(conn), p->path)) {
if (strlen(p->path) == path.len && !strncmp(path.p, p->path, path.len)) {
p->handler(conn);
return true;
}
Expand All @@ -332,9 +315,8 @@ static int on_message_complete_cb(struct http_parser *parser)
{
struct uh_connection *conn = (struct uh_connection *)parser->data;
struct uh_request *req = &conn->req;
int i;

http_parser_parse_url(O2D(conn, req->url.offset), req->url.length, false, &conn->url_parser);
http_parser_parse_url(req->url.p, req->url.len, false, &conn->url_parser);

if (!run_plugins(conn)) {
if (conn->srv->on_request)
Expand All @@ -345,19 +327,6 @@ static int on_message_complete_cb(struct http_parser *parser)

buffer_pull(&conn->rb, NULL, buffer_length(&conn->rb));

if (req->url.path)
free(req->url.path);

if (req->url.query)
free(req->url.query);

for (i = 0; i < UHTTPD_MAX_HEADER_NUM; i++) {
if (req->headers[i].name)
free(req->headers[i].name);
if (req->headers[i].value)
free(req->headers[i].value);
}

memset(req, 0, sizeof(struct uh_request));

return 0;
Expand Down Expand Up @@ -441,7 +410,7 @@ static void conn_write_cb(struct ev_loop *loop, struct ev_io *w, int revents)

if (buffer_length(&conn->wb) == 0) {
if (conn->file.fd > 0) {
ssize_t ret = sendfile(w->fd, conn->file.fd, NULL, conn->file.size);
ret = sendfile(w->fd, conn->file.fd, NULL, conn->file.size);
if (ret < 0) {
if (errno != EAGAIN) {
uh_log_err("write error: %s\n", strerror(errno));
Expand Down
35 changes: 13 additions & 22 deletions src/connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,31 +41,22 @@

struct uh_server;

struct uh_str {
const char *p;
size_t len;
};

struct uh_request {
struct {
int length;
int offset;
char *path;
char *query;
} url;
struct uh_str url;

struct {
int name_offset;
int name_len;
int value_offset;
int value_len;
} headers_info[UHTTPD_MAX_HEADER_NUM];
int header_num;
bool last_was_header_value;
struct {
char *name;
char *value;
struct uh_str field;
struct uh_str value;
} headers[UHTTPD_MAX_HEADER_NUM];

struct {
int offset;
int len;
} body;
struct uh_str body;
};

struct uh_connection {
Expand Down Expand Up @@ -107,10 +98,10 @@ struct uh_connection {
void (*chunk_end)(struct uh_connection *conn);
enum http_method (*get_method)(struct uh_connection *conn);
const char *(*get_method_str)(struct uh_connection *conn);
const char *(*get_path)(struct uh_connection *conn);
const char *(*get_query)(struct uh_connection *conn);
const char *(*get_header)(struct uh_connection *conn, const char *name);
const char *(*get_body)(struct uh_connection *conn, int *len);
const struct uh_str (*get_path)(struct uh_connection *conn);
const struct uh_str (*get_query)(struct uh_connection *conn);
const struct uh_str (*get_header)(struct uh_connection *conn, const char *name);
const struct uh_str (*get_body)(struct uh_connection *conn);
};

struct uh_connection *uh_new_connection(struct uh_server *srv, int sock, struct sockaddr_in *addr);
Expand Down
Loading

0 comments on commit 28c8146

Please sign in to comment.