From 6beab9603136be0174e44665a57d29548a73e4c7 Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Thu, 9 Jan 2025 23:02:25 -0800 Subject: [PATCH] http: more deduplication of code, and capture content-length on parse without alloc --- src/supplemental/http/http_api.h | 21 +- src/supplemental/http/http_conn.c | 222 +++++++++++++------- src/supplemental/http/http_msg.c | 314 +++++----------------------- src/supplemental/http/http_msg.h | 34 ++- src/supplemental/http/http_server.c | 12 +- 5 files changed, 217 insertions(+), 386 deletions(-) diff --git a/src/supplemental/http/http_api.h b/src/supplemental/http/http_api.h index e1ff80eb7..b2b07b992 100644 --- a/src/supplemental/http/http_api.h +++ b/src/supplemental/http/http_api.h @@ -116,19 +116,11 @@ extern void nni_http_read_res(nni_http_conn *, nni_aio *); extern void nni_http_read_req(nni_http_conn *, nni_aio *); extern void nni_http_write_res(nni_http_conn *, nni_aio *); -extern const char *nni_http_req_get_header(const nni_http_req *, const char *); -extern const char *nni_http_res_get_header(const nni_http_res *, const char *); extern int nni_http_req_add_header(nni_http_req *, const char *, const char *); -extern int nni_http_res_add_header(nni_http_res *, const char *, const char *); -extern int nni_http_req_set_header(nni_http_req *, const char *, const char *); -extern int nni_http_res_set_header(nni_http_res *, const char *, const char *); extern int nni_http_req_del_header(nni_http_req *, const char *); extern int nni_http_res_del_header(nni_http_res *, const char *); -extern int nni_http_res_set_data(nni_http_res *, const void *, size_t); extern int nni_http_req_alloc_data(nni_http_req *, size_t); extern int nni_http_res_alloc_data(nni_http_res *, size_t); -extern void nni_http_res_set_content_type(nni_http_res *, const char *); -extern void nni_http_req_set_content_type(nni_http_req *, const char *); extern bool nni_http_res_is_error(nni_http_res *); @@ -369,7 +361,7 @@ extern void nni_http_transact( extern const char *nni_http_stream_scheme(const char *); // Private method used for the server. -extern bool nni_http_conn_res_sent(nni_http_conn *conn); +extern bool nni_http_res_sent(nni_http_conn *conn); extern const char *nni_http_get_version(nng_http *conn); extern int nni_http_set_version(nng_http *conn, const char *vers); @@ -399,17 +391,14 @@ extern int nni_http_set_uri( extern const char *nni_http_get_uri(nng_http *conn); extern void nni_http_set_host(nng_http *conn, const char *); +extern void nni_http_set_content_type(nng_http *conn, const char *); extern void nni_http_conn_reset(nng_http *conn); -extern int nni_http_add_request_header( +extern int nni_http_add_header( nng_http *conn, const char *key, const char *val); -extern int nni_http_set_request_header( - nng_http *conn, const char *key, const char *val); -extern int nni_http_add_response_header( - nng_http *conn, const char *key, const char *val); -extern int nni_http_set_response_header( - nng_http *conn, const char *key, const char *val); extern void nni_http_set_static_header( nng_http *conn, nni_http_header *header, const char *key, const char *val); +extern bool nni_http_parsed(nng_http *conn); + #endif // NNG_SUPPLEMENTAL_HTTP_HTTP_API_H diff --git a/src/supplemental/http/http_conn.c b/src/supplemental/http/http_conn.c index 49e6eabf8..20ae2f053 100644 --- a/src/supplemental/http/http_conn.c +++ b/src/supplemental/http/http_conn.c @@ -213,7 +213,9 @@ http_rd_buf(nni_http_conn *conn, nni_aio *aio) return (NNG_EAGAIN); case HTTP_RD_REQ: - rv = nni_http_req_parse(conn, rbuf, cnt, &n); + conn->client = true; + rv = nni_http_req_parse(conn, rbuf, cnt, &n); + conn->client = false; conn->rd_get += n; if (conn->rd_get == conn->rd_put) { conn->rd_get = conn->rd_put = 0; @@ -233,7 +235,9 @@ http_rd_buf(nni_http_conn *conn, nni_aio *aio) return (rv); case HTTP_RD_RES: - rv = nni_http_res_parse(conn, rbuf, cnt, &n); + conn->client = false; + rv = nni_http_res_parse(conn, rbuf, cnt, &n); + conn->client = true; conn->rd_get += n; if (conn->rd_get == conn->rd_put) { conn->rd_get = conn->rd_put = 0; @@ -905,8 +909,7 @@ http_conn_set_error(nng_http *conn, uint16_t status, const char *reason, body = content; } if (strlen(body) > 0) { - nni_http_set_static_header(conn, &conn->res.content_type, - "Content-Type", "text/html; charset=UTF-8"); + nni_http_set_content_type(conn, "text/html; charset=UTF-8"); return (nni_http_copy_body(conn, body, strlen(body))); } return (0); @@ -934,7 +937,7 @@ nni_http_set_redirect( conn->res.location.value = loc; conn->res.location.static_name = true; conn->res.location.static_value = false; - nni_list_prepend(&conn->res.hdrs, &conn->res.location); + nni_list_prepend(&conn->res.data.hdrs, &conn->res.location); return (http_conn_set_error(conn, status, reason, NULL, redirect)); } @@ -950,7 +953,28 @@ nni_http_set_host(nng_http *conn, const char *host) conn->req.host_header.static_name = true; conn->req.host_header.static_value = true; conn->req.host_header.alloc_header = false; - nni_list_prepend(&conn->req.hdrs, &conn->req.host_header); + nni_list_prepend(&conn->req.data.hdrs, &conn->req.host_header); +} + +void +nni_http_set_content_length(nng_http *conn, size_t size) +{ + nni_http_entity *data = + conn->client ? &conn->req.data : &conn->res.data; + + snprintf(data->clen, sizeof(data->clen), "%lu", (unsigned long) size); + nni_http_set_static_header( + conn, &data->content_length, "Content-Length", data->clen); +} + +void +nni_http_set_content_type(nng_http *conn, const char *ctype) +{ + nni_http_entity *data = + conn->client ? &conn->req.data : &conn->res.data; + snprintf(data->ctype, sizeof(data->ctype), "%s", ctype); + nni_http_set_static_header( + conn, &data->content_type, "Content-Type", data->ctype); } const char * @@ -998,69 +1022,117 @@ nni_http_set_uri(nng_http *conn, const char *uri, const char *query) return (0); } -static bool -http_set_request_known_header(nng_http *conn, const char *key, const char *val) +static int +http_set_header(nng_http *conn, const char *key, const char *val) { - if (nni_strcasecmp(key, "Host") == 0) { - nni_http_set_host(conn, val); - return (true); - } - if (nni_strcasecmp(key, "Content-Type") == 0) { - nni_http_req_set_content_type(&conn->req, val); - return (true); - } - return (false); -} + nni_http_entity *data = + conn->client ? &conn->req.data : &conn->res.data; + http_header *h; -int -nni_http_add_request_header(nng_http *conn, const char *key, const char *val) -{ - if (http_set_request_known_header(conn, key, val)) { - return (0); + NNI_LIST_FOREACH (&data->hdrs, h) { + if (nni_strcasecmp(key, h->name) == 0) { + char *news; + if ((news = nni_strdup(val)) == NULL) { + return (NNG_ENOMEM); + } + if (!h->static_value) { + nni_strfree(h->value); + h->value = NULL; + } + h->value = news; + return (0); + } } - return (nni_http_req_add_header(&conn->req, key, val)); + if ((h = NNI_ALLOC_STRUCT(h)) == NULL) { + return (NNG_ENOMEM); + } + h->alloc_header = true; + if ((h->name = nni_strdup(key)) == NULL) { + NNI_FREE_STRUCT(h); + return (NNG_ENOMEM); + } + if ((h->value = nni_strdup(val)) == NULL) { + nni_strfree(h->name); + NNI_FREE_STRUCT(h); + return (NNG_ENOMEM); + } + nni_list_append(&data->hdrs, h); + return (0); } -int -nni_http_set_request_header(nng_http *conn, const char *key, const char *val) +static int +http_add_header(nng_http *conn, const char *key, const char *val) { - if (http_set_request_known_header(conn, key, val)) { - return (0); + nni_http_entity *data = + conn->client ? &conn->req.data : &conn->res.data; + http_header *h; + NNI_LIST_FOREACH (&data->hdrs, h) { + if (nni_strcasecmp(key, h->name) == 0) { + char *news; + int rv; + rv = nni_asprintf(&news, "%s, %s", h->value, val); + if (rv != 0) { + return (rv); + } + if (!h->static_value) { + nni_strfree(h->value); + } + h->value = news; + return (0); + } } - return (nni_http_req_set_header(&conn->req, key, val)); + if ((h = NNI_ALLOC_STRUCT(h)) == NULL) { + return (NNG_ENOMEM); + } + h->alloc_header = true; + if ((h->name = nni_strdup(key)) == NULL) { + NNI_FREE_STRUCT(h); + return (NNG_ENOMEM); + } + if ((h->value = nni_strdup(val)) == NULL) { + nni_strfree(h->name); + NNI_FREE_STRUCT(h); + return (NNG_ENOMEM); + } + nni_list_append(&data->hdrs, h); + return (0); } static bool -http_set_response_known_header( - nng_http *conn, const char *key, const char *val) +http_set_known_header(nng_http *conn, const char *key, const char *val) { if (nni_strcasecmp(key, "Content-Type") == 0) { - nni_http_res_set_content_type(&conn->res, val); + nni_http_set_content_type(conn, val); return (true); } - return (false); -} - -int -nni_http_add_response_header(nng_http *conn, const char *key, const char *val) -{ - if (http_set_response_known_header(conn, key, val)) { - return (0); + if (nni_strcasecmp(key, "Content-Length") == 0) { + nni_http_entity *data = + conn->client ? &conn->req.data : &conn->res.data; + snprintf(data->clen, sizeof(data->clen), "%s", val); + nni_http_set_static_header( + conn, &data->content_length, "Content-Length", data->clen); + return (true); } - return (nni_http_res_add_header(&conn->res, key, val)); + if (conn->client) { + if (nni_strcasecmp(key, "Host") == 0) { + nni_http_set_host(conn, val); + return (true); + } + } + return (false); } int -nni_http_set_response_header(nng_http *conn, const char *key, const char *val) +nni_http_add_header(nng_http *conn, const char *key, const char *val) { - if (http_set_response_known_header(conn, key, val)) { + if (http_set_known_header(conn, key, val)) { return (0); } - return (nni_http_res_set_header(&conn->res, key, val)); + return (http_add_header(conn, key, val)); } void @@ -1069,9 +1141,9 @@ nni_http_set_static_header( { nni_list *headers; if (conn->client) { - headers = &conn->req.hdrs; + headers = &conn->req.data.hdrs; } else { - headers = &conn->res.hdrs; + headers = &conn->res.data.hdrs; } nni_http_del_header(conn, key); @@ -1087,30 +1159,32 @@ nni_http_set_static_header( int nni_http_set_header(nng_http *conn, const char *key, const char *val) { - if (conn->client) { - return (nni_http_set_request_header(conn, key, val)); - } else { - return (nni_http_set_response_header(conn, key, val)); + if (http_set_known_header(conn, key, val)) { + return (0); } + return (http_set_header(conn, key, val)); } -int -nni_http_add_header(nng_http *conn, const char *key, const char *val) +static bool +http_del_header_one(nni_list *hdrs, const char *key) { - if (conn->client) { - return (nni_http_add_request_header(conn, key, val)); - } else { - return (nni_http_add_response_header(conn, key, val)); + http_header *h; + NNI_LIST_FOREACH (hdrs, h) { + if (nni_strcasecmp(key, h->name) == 0) { + nni_http_free_header(h); + return (true); + } } + return (false); } void nni_http_del_header(nng_http *conn, const char *key) { - if (conn->client) { - nni_http_req_del_header(&conn->req, key); - } else { - nni_http_res_del_header(&conn->res, key); + nni_list *hdrs = + conn->client ? &conn->req.data.hdrs : &conn->res.data.hdrs; + while (http_del_header_one(hdrs, key)) { + continue; } } @@ -1130,9 +1204,9 @@ const char * nni_http_get_header(nng_http *conn, const char *key) { if (conn->client) { - return (http_get_header(&conn->res.hdrs, key)); + return (http_get_header(&conn->res.data.hdrs, key)); } else { - return (http_get_header(&conn->req.hdrs, key)); + return (http_get_header(&conn->req.data.hdrs, key)); } } @@ -1183,22 +1257,6 @@ http_copy_data(nni_http_entity *entity, const void *data, size_t size) return (rv); } -void -nni_http_set_content_length(nng_http *conn, size_t size) -{ - if (conn->client) { - snprintf(conn->req.clen, sizeof(conn->req.clen), "%lu", - (unsigned long) size); - nni_http_set_static_header(conn, &conn->req.content_length, - "Content-Length", conn->req.clen); - } else { - snprintf(conn->res.clen, sizeof(conn->res.clen), "%lu", - (unsigned long) size); - nni_http_set_static_header(conn, &conn->res.content_length, - "Content-Length", conn->res.clen); - } -} - void nni_http_set_body(nng_http *conn, void *data, size_t size) { @@ -1319,7 +1377,13 @@ nni_http_conn_init(nni_http_conn **connp, nng_stream *stream, bool client) // private to the HTTP framework, used on the server bool -nni_http_conn_res_sent(nni_http_conn *conn) +nni_http_res_sent(nni_http_conn *conn) { return (conn->res_sent); } + +bool +nni_http_parsed(nng_http *conn) +{ + return (conn->client ? conn->res.data.parsed : conn->req.data.parsed); +} diff --git a/src/supplemental/http/http_msg.c b/src/supplemental/http/http_msg.c index 964289e4d..988bb37e6 100644 --- a/src/supplemental/http/http_msg.c +++ b/src/supplemental/http/http_msg.c @@ -52,40 +52,35 @@ http_entity_reset(nni_http_entity *entity) if (entity->own && entity->size) { nni_free(entity->data, entity->size); } - entity->data = NULL; - entity->size = 0; - entity->own = false; + http_headers_reset(&entity->hdrs); + nni_free(entity->buf, entity->bufsz); + entity->data = NULL; + entity->size = 0; + entity->own = false; + entity->parsed = false; + entity->buf = NULL; + entity->bufsz = 0; } void nni_http_req_reset(nni_http_req *req) { - http_headers_reset(&req->hdrs); http_entity_reset(&req->data); if (req->uri != req->ubuf) { nni_strfree(req->uri); } req->uri = NULL; - nni_free(req->buf, req->bufsz); (void) snprintf(req->meth, sizeof(req->meth), "GET"); - req->bufsz = 0; - req->buf = NULL; - req->parsed = false; } void nni_http_res_reset(nni_http_res *res) { - http_headers_reset(&res->hdrs); http_entity_reset(&res->data); nni_strfree(res->rsn); - res->vers = NNG_HTTP_VERSION_1_1; - res->rsn = NULL; - res->code = 0; - res->parsed = false; - nni_free(res->buf, res->bufsz); - res->buf = NULL; - res->bufsz = 0; + res->vers = NNG_HTTP_VERSION_1_1; + res->rsn = NULL; + res->code = 0; } static int @@ -105,7 +100,7 @@ int nni_http_req_del_header(nni_http_req *req, const char *key) { int rv = NNG_ENOENT; - while (http_del_header(&req->hdrs, key) == 0) { + while (http_del_header(&req->data.hdrs, key) == 0) { rv = 0; } return (rv); @@ -115,132 +110,12 @@ int nni_http_res_del_header(nni_http_res *res, const char *key) { int rv = NNG_ENOENT; - while (http_del_header(&res->hdrs, key) == 0) { + while (http_del_header(&res->data.hdrs, key) == 0) { rv = 0; } return (rv); } -static int -http_set_header(nni_list *hdrs, const char *key, const char *val) -{ - http_header *h; - - NNI_LIST_FOREACH (hdrs, h) { - if (nni_strcasecmp(key, h->name) == 0) { - char *news; - if ((news = nni_strdup(val)) == NULL) { - return (NNG_ENOMEM); - } - if (!h->static_value) { - nni_strfree(h->value); - h->value = NULL; - } - h->value = news; - return (0); - } - } - - if ((h = NNI_ALLOC_STRUCT(h)) == NULL) { - return (NNG_ENOMEM); - } - h->alloc_header = true; - if ((h->name = nni_strdup(key)) == NULL) { - NNI_FREE_STRUCT(h); - return (NNG_ENOMEM); - } - if ((h->value = nni_strdup(val)) == NULL) { - nni_strfree(h->name); - NNI_FREE_STRUCT(h); - return (NNG_ENOMEM); - } - nni_list_append(hdrs, h); - return (0); -} - -int -nni_http_req_set_header(nni_http_req *req, const char *key, const char *val) -{ - return (http_set_header(&req->hdrs, key, val)); -} - -int -nni_http_res_set_header(nni_http_res *res, const char *key, const char *val) -{ - return (http_set_header(&res->hdrs, key, val)); -} - -static int -http_add_header(nni_list *hdrs, const char *key, const char *val) -{ - http_header *h; - NNI_LIST_FOREACH (hdrs, h) { - if (nni_strcasecmp(key, h->name) == 0) { - char *news; - int rv; - rv = nni_asprintf(&news, "%s, %s", h->value, val); - if (rv != 0) { - return (rv); - } - nni_strfree(h->value); - h->value = news; - return (0); - } - } - - if ((h = NNI_ALLOC_STRUCT(h)) == NULL) { - return (NNG_ENOMEM); - } - h->alloc_header = true; - if ((h->name = nni_strdup(key)) == NULL) { - NNI_FREE_STRUCT(h); - return (NNG_ENOMEM); - } - if ((h->value = nni_strdup(val)) == NULL) { - nni_strfree(h->name); - NNI_FREE_STRUCT(h); - return (NNG_ENOMEM); - } - nni_list_append(hdrs, h); - return (0); -} - -int -nni_http_req_add_header(nni_http_req *req, const char *key, const char *val) -{ - return (http_add_header(&req->hdrs, key, val)); -} - -int -nni_http_res_add_header(nni_http_res *res, const char *key, const char *val) -{ - return (http_add_header(&res->hdrs, key, val)); -} - -static const char * -http_get_header(const nni_list *hdrs, const char *key) -{ - http_header *h; - NNI_LIST_FOREACH (hdrs, h) { - if (nni_strcasecmp(h->name, key) == 0) { - return (h->value); - } - } - return (NULL); -} - -const char * -nni_http_req_get_header(const nni_http_req *req, const char *key) -{ - return (http_get_header(&req->hdrs, key)); -} - -const char * -nni_http_res_get_header(const nni_http_res *res, const char *key) -{ - return (http_get_header(&res->hdrs, key)); -} - // http_entity_set_data sets the entity, but does not update the // content-length header. static void @@ -268,67 +143,6 @@ http_entity_alloc_data(nni_http_entity *entity, size_t size) return (0); } -void -nni_http_req_set_content_length(nni_http_req *req, size_t size) -{ - snprintf(req->clen, sizeof(req->clen), "%lu", (unsigned long) size); - nni_http_req_del_header(req, "Content-Length"); - nni_list_node_remove(&req->content_length.node); - req->content_length.name = "Content-Length"; - req->content_length.value = req->clen; - req->content_length.static_name = true; - req->content_length.static_value = true; - nni_list_append(&req->hdrs, &req->content_length); -} - -void -nni_http_res_set_content_length(nni_http_res *res, size_t size) -{ - snprintf(res->clen, sizeof(res->clen), "%lu", (unsigned long) size); - nni_http_res_del_header(res, "Content-Length"); - nni_list_node_remove(&res->content_length.node); - res->content_length.name = "Content-Length"; - res->content_length.value = res->clen; - res->content_length.static_name = true; - res->content_length.static_value = true; - nni_list_append(&res->hdrs, &res->content_length); -} - -void -nni_http_res_set_content_type(nni_http_res *res, const char *ctype) -{ - snprintf(res->ctype, sizeof(res->ctype), "%s", ctype); - nni_http_res_del_header(res, "Content-Type"); - nni_list_node_remove(&res->content_type.node); - res->content_type.name = "Content-Type"; - res->content_type.value = res->ctype; - res->content_type.static_name = true; - res->content_type.static_value = true; - nni_list_append(&res->hdrs, &res->content_type); -} - -void -nni_http_req_set_content_type(nni_http_req *req, const char *ctype) -{ - snprintf(req->ctype, sizeof(req->ctype), "%s", ctype); - nni_http_req_del_header(req, "Content-Type"); - nni_list_node_remove(&req->content_type.node); - req->content_type.name = "Content-Type"; - req->content_type.value = req->ctype; - req->content_type.static_name = true; - req->content_type.static_value = true; - nni_list_append(&req->hdrs, &req->content_type); -} - -int -nni_http_res_set_data(nni_http_res *res, const void *data, size_t size) -{ - http_entity_set_data(&res->data, data, size); - nni_http_res_set_content_length(res, size); - res->iserr = false; - return (0); -} - int nni_http_req_alloc_data(nni_http_req *req, size_t size) { @@ -361,35 +175,7 @@ nni_http_res_is_error(nni_http_res *res) } static int -http_req_parse_header(nng_http *conn, void *line) -{ - char *key = line; - char *val; - char *end; - - // Find separation between key and value - if ((val = strchr(key, ':')) == NULL) { - return (NNG_EPROTO); - } - - // Trim leading and trailing whitespace from header - *val = '\0'; - val++; - while (*val == ' ' || *val == '\t') { - val++; - } - end = val + strlen(val); - end--; - while ((end > val) && (*end == ' ' || *end == '\t')) { - *end = '\0'; - end--; - } - - return (nni_http_add_request_header(conn, key, val)); -} - -static int -http_res_parse_header(nng_http *conn, void *line) +http_parse_header(nng_http *conn, void *line) { char *key = line; char *val; @@ -413,7 +199,7 @@ http_res_parse_header(nng_http *conn, void *line) end--; } - return (nni_http_add_response_header(conn, key, val)); + return (nni_http_add_header(conn, key, val)); } // http_sprintf_headers makes headers for an HTTP request or an HTTP response @@ -489,8 +275,8 @@ http_req_prepare(nni_http_req *req) if (req->uri == NULL) { return (NNG_EINVAL); } - rv = http_asprintf(&req->buf, &req->bufsz, &req->hdrs, "%s %s %s\r\n", - req->meth, req->uri, req->vers); + rv = http_asprintf(&req->data.buf, &req->data.bufsz, &req->data.hdrs, + "%s %s %s\r\n", req->meth, req->uri, req->vers); return (rv); } @@ -503,8 +289,8 @@ http_res_prepare(nng_http *conn) if (res->code == 0) { res->code = NNG_HTTP_STATUS_OK; } - rv = http_asprintf(&res->buf, &res->bufsz, &res->hdrs, "%s %d %s\r\n", - res->vers, res->code, nni_http_get_reason(conn)); + rv = http_asprintf(&res->data.buf, &res->data.bufsz, &res->data.hdrs, + "%s %d %s\r\n", res->vers, res->code, nni_http_get_reason(conn)); return (rv); } @@ -513,53 +299,53 @@ nni_http_req_get_buf(nni_http_req *req, void **data, size_t *szp) { int rv; - if ((req->buf == NULL) && (rv = http_req_prepare(req)) != 0) { + if ((req->data.buf == NULL) && (rv = http_req_prepare(req)) != 0) { return (rv); } - *data = req->buf; - *szp = req->bufsz - 1; // exclude terminating NUL + *data = req->data.buf; + *szp = req->data.bufsz - 1; // exclude terminating NUL return (0); } int -nni_http_res_get_buf(nni_http_conn *conn, void **data, size_t *szp) +nni_http_res_get_buf(nng_http *conn, void **data, size_t *szp) { int rv; nni_http_res *res = nni_http_conn_res(conn); - if ((res->buf == NULL) && (rv = http_res_prepare(conn)) != 0) { + if ((res->data.buf == NULL) && (rv = http_res_prepare(conn)) != 0) { return (rv); } - *data = res->buf; - *szp = res->bufsz - 1; // exclude terminating NUL + *data = res->data.buf; + *szp = res->data.bufsz - 1; // exclude terminating NUL return (0); } void nni_http_req_init(nni_http_req *req) { - NNI_LIST_INIT(&req->hdrs, http_header, node); - req->buf = NULL; - req->bufsz = 0; - req->data.data = NULL; - req->data.size = 0; - req->data.own = false; - req->uri = NULL; + NNI_LIST_INIT(&req->data.hdrs, http_header, node); + req->data.buf = NULL; + req->data.bufsz = 0; + req->data.data = NULL; + req->data.size = 0; + req->data.own = false; + req->uri = NULL; (void) snprintf(req->meth, sizeof(req->meth), "GET"); } void nni_http_res_init(nni_http_res *res) { - NNI_LIST_INIT(&res->hdrs, http_header, node); - res->buf = NULL; - res->bufsz = 0; - res->data.data = NULL; - res->data.size = 0; - res->data.own = false; - res->vers = NNG_HTTP_VERSION_1_1; - res->rsn = NULL; - res->code = 0; + NNI_LIST_INIT(&res->data.hdrs, http_header, node); + res->data.buf = NULL; + res->data.bufsz = 0; + res->data.data = NULL; + res->data.size = 0; + res->data.own = false; + res->vers = NNG_HTTP_VERSION_1_1; + res->rsn = NULL; + res->code = 0; } static int @@ -691,10 +477,10 @@ nni_http_req_parse(nng_http *conn, void *buf, size_t n, size_t *lenp) break; } - if (req->parsed) { - rv = http_req_parse_header(conn, line); + if (req->data.parsed) { + rv = http_parse_header(conn, line); } else if ((rv = http_req_parse_line(conn, line)) == 0) { - req->parsed = true; + req->data.parsed = true; } if (rv != 0) { @@ -703,7 +489,7 @@ nni_http_req_parse(nng_http *conn, void *buf, size_t n, size_t *lenp) } if (rv == 0) { - req->parsed = false; + req->data.parsed = false; } *lenp = len; return (rv); @@ -732,10 +518,10 @@ nni_http_res_parse(nng_http *conn, void *buf, size_t n, size_t *lenp) break; } - if (res->parsed) { - rv = http_res_parse_header(conn, line); + if (res->data.parsed) { + rv = http_parse_header(conn, line); } else if ((rv = http_res_parse_line(conn, line)) == 0) { - res->parsed = true; + res->data.parsed = true; } if (rv != 0) { @@ -744,7 +530,7 @@ nni_http_res_parse(nng_http *conn, void *buf, size_t n, size_t *lenp) } if (rv == 0) { - res->parsed = false; + res->data.parsed = false; } *lenp = len; return (rv); diff --git a/src/supplemental/http/http_msg.h b/src/supplemental/http/http_msg.h index 876eea6d6..e08dab8a7 100644 --- a/src/supplemental/http/http_msg.h +++ b/src/supplemental/http/http_msg.h @@ -29,44 +29,36 @@ typedef struct http_header { typedef struct http_header nni_http_header; typedef struct nni_http_entity { - char *data; - size_t size; - bool own; // if true, data is "ours", and should be freed + char *data; + size_t size; + bool own; // if true, data is "ours", and should be freed + char clen[24]; // 64-bit lengths, in decimal + char ctype[128]; // 63+63+; per RFC 6838 + http_header content_type; + http_header content_length; + nni_list hdrs; + char *buf; + size_t bufsz; + bool parsed; } nni_http_entity; struct nng_http_req { - nni_list hdrs; nni_http_entity data; char meth[32]; - char clen[24]; // 64-bit lengths, in decimal - char ctype[128]; // 63+63+; per RFC 6838 - char host[260]; // 253 per IETF, plus 6 for :port plus null - char ubuf[200]; // Most URIs are smaller than this + char host[260]; // 253 per IETF, plus 6 for :port plus null + char ubuf[200]; // Most URIs are smaller than this char *uri; const char *vers; - char *buf; - size_t bufsz; - bool parsed; - http_header content_type; - http_header content_length; http_header host_header; }; struct nng_http_res { - nni_list hdrs; nni_http_entity data; uint16_t code; char *rsn; const char *vers; - char *buf; - size_t bufsz; - bool parsed; bool iserr; - char clen[24]; - char ctype[128]; // RFC 6838 http_header location; - http_header content_type; - http_header content_length; }; extern void nni_http_free_header(http_header *); diff --git a/src/supplemental/http/http_server.c b/src/supplemental/http/http_server.c index 8771a04be..7fbd7a56d 100644 --- a/src/supplemental/http/http_server.c +++ b/src/supplemental/http/http_server.c @@ -525,8 +525,9 @@ http_sconn_rxdone(void *arg) if (rv == NNG_EMSGSIZE) { sc->close = true; http_sconn_error(sc, - req->parsed ? NNG_HTTP_STATUS_HEADERS_TOO_LARGE - : NNG_HTTP_STATUS_URI_TOO_LONG); + nni_http_parsed(sc->conn) + ? NNG_HTTP_STATUS_HEADERS_TOO_LARGE + : NNG_HTTP_STATUS_URI_TOO_LONG); } else { http_sconn_close(sc); } @@ -731,7 +732,7 @@ http_sconn_cbdone(void *arg) return; } res = nni_http_conn_res(sc->conn); - if (!nni_http_conn_res_sent(sc->conn)) { + if (!nni_http_res_sent(sc->conn)) { const char *val; const char *method; uint16_t status; @@ -742,7 +743,7 @@ http_sconn_cbdone(void *arg) sc->close = true; } if (sc->close) { - nni_http_res_set_header(res, "Connection", "close"); + nni_http_set_header(sc->conn, "Connection", "close"); } if ((strcmp(method, "HEAD") == 0) && status >= 200 && status <= 299) { @@ -1585,8 +1586,7 @@ http_handle_redirect(nng_http *conn, void *data, nng_aio *aio) // keeps us from having to consume the entity body, we can just // discard it. if (((rv = nni_http_set_redirect(conn, hr->code, NULL, loc)) != 0) || - ((rv = nni_http_res_set_header(res, "Connection", "close")) != - 0)) { + ((rv = nni_http_set_header(conn, "Connection", "close")) != 0)) { if (loc != hr->where) { nni_strfree(loc); }