diff --git a/src/supplemental/http/http_api.h b/src/supplemental/http/http_api.h index 02b5fbe45..c8d73788c 100644 --- a/src/supplemental/http/http_api.h +++ b/src/supplemental/http/http_api.h @@ -119,7 +119,7 @@ extern int nni_http_req_add_header(nni_http_req *, const char *, const char *); 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 bool nni_http_res_is_error(nni_http_res *); +extern bool nni_http_is_error(nng_http *); extern void nni_http_read(nni_http_conn *, nni_aio *); extern void nni_http_read_full(nni_http_conn *, nni_aio *); diff --git a/src/supplemental/http/http_conn.c b/src/supplemental/http/http_conn.c index 824baa96d..65c240f55 100644 --- a/src/supplemental/http/http_conn.c +++ b/src/supplemental/http/http_conn.c @@ -76,12 +76,17 @@ struct nng_http_conn { size_t rd_put; size_t rd_discard; + // some common headers + http_header host_header; // request + http_header location; // response (redirects) + enum read_flavor rd_flavor; enum write_flavor wr_flavor; - bool rd_buffered; + bool buffered; bool client; // true if a client's connection bool res_sent; bool closed; + bool iserr; }; nng_http_req * @@ -220,7 +225,7 @@ http_rd_buf(nni_http_conn *conn, nni_aio *aio) // (Note that we get here if we either have not completed // a full transaction on a FULL read, or were not even able // to get *any* data for a partial RAW read.) - conn->rd_buffered = false; + conn->buffered = false; nni_aio_set_iov(&conn->rd_aio, nio, iov); nng_stream_recv(conn->sock, &conn->rd_aio); return (NNG_EAGAIN); @@ -235,9 +240,9 @@ http_rd_buf(nni_http_conn *conn, nni_aio *aio) http_buf_pull_up(conn); if (conn->rd_discard > 0) { nni_iov iov1; - iov1.iov_buf = conn->buf + conn->rd_put; - iov1.iov_len = conn->bufsz - conn->rd_put; - conn->rd_buffered = true; + iov1.iov_buf = conn->buf + conn->rd_put; + iov1.iov_len = conn->bufsz - conn->rd_put; + conn->buffered = true; nni_aio_set_iov(&conn->rd_aio, 1, &iov1); nng_stream_recv(conn->sock, &conn->rd_aio); return (NNG_EAGAIN); @@ -255,9 +260,9 @@ http_rd_buf(nni_http_conn *conn, nni_aio *aio) if (rv == NNG_EAGAIN) { nni_iov iov1; http_buf_pull_up(conn); - iov1.iov_buf = conn->buf + conn->rd_put; - iov1.iov_len = conn->bufsz - conn->rd_put; - conn->rd_buffered = true; + iov1.iov_buf = conn->buf + conn->rd_put; + iov1.iov_len = conn->bufsz - conn->rd_put; + conn->buffered = true; if (iov1.iov_len == 0) { return (NNG_EMSGSIZE); } @@ -277,9 +282,9 @@ http_rd_buf(nni_http_conn *conn, nni_aio *aio) if (rv == NNG_EAGAIN) { nni_iov iov1; http_buf_pull_up(conn); - iov1.iov_buf = conn->buf + conn->rd_put; - iov1.iov_len = conn->bufsz - conn->rd_put; - conn->rd_buffered = true; + iov1.iov_buf = conn->buf + conn->rd_put; + iov1.iov_len = conn->bufsz - conn->rd_put; + conn->buffered = true; if (iov1.iov_len == 0) { return (NNG_EMSGSIZE); } @@ -297,9 +302,9 @@ http_rd_buf(nni_http_conn *conn, nni_aio *aio) } if (rv == NNG_EAGAIN) { nni_iov iov1; - iov1.iov_buf = conn->buf + conn->rd_put; - iov1.iov_len = conn->bufsz - conn->rd_put; - conn->rd_buffered = true; + iov1.iov_buf = conn->buf + conn->rd_put; + iov1.iov_len = conn->bufsz - conn->rd_put; + conn->buffered = true; nni_aio_set_iov(&conn->rd_aio, 1, &iov1); nng_stream_recv(conn->sock, &conn->rd_aio); } @@ -371,7 +376,7 @@ http_rd_cb(void *arg) cnt = nni_aio_count(aio); // If we were reading into the buffer, then advance location(s). - if (conn->rd_buffered) { + if (conn->buffered) { conn->rd_put += cnt; NNI_ASSERT(conn->rd_put <= conn->bufsz); http_rd_start(conn); @@ -1001,6 +1006,12 @@ nni_http_set_status(nng_http *conn, uint16_t status, const char *reason) conn->rsn = dup; } +bool +nni_http_is_error(nng_http *conn) +{ + return (conn->iserr); +} + static int http_conn_set_error(nng_http *conn, uint16_t status, const char *reason, const char *body, const char *redirect) @@ -1023,7 +1034,7 @@ http_conn_set_error(nng_http *conn, uint16_t status, const char *reason, "

%s

"; const char *suffix = "

"; - conn->res.iserr = true; + conn->iserr = true; nni_http_set_status(conn, status, reason); reason = nni_http_get_reason(conn); @@ -1072,17 +1083,26 @@ nni_http_set_redirect( nng_http *conn, uint16_t status, const char *reason, const char *redirect) { char *loc; - if ((loc = nni_strdup(redirect)) == NULL) { + bool static_value = false; + + // The only users of this api, call do not use the URL buffer after + // doing so, so we can optimize and use that for most redirections (no + // more allocs!) + if (strlen(redirect) < sizeof(conn->ubuf)) { + snprintf(conn->ubuf, sizeof(conn->ubuf), "%s", redirect); + loc = conn->ubuf; + static_value = true; + } else if ((loc = nni_strdup(redirect)) == NULL) { return (NNG_ENOMEM); } (void) nni_http_del_header(conn, "Location"); - nni_list_node_remove(&conn->res.location.node); - nni_http_free_header(&conn->res.location); - conn->res.location.name = "Location"; - conn->res.location.value = loc; - conn->res.location.static_name = true; - conn->res.location.static_value = false; - nni_list_prepend(&conn->res.data.hdrs, &conn->res.location); + nni_list_node_remove(&conn->location.node); + nni_http_free_header(&conn->location); + conn->location.name = "Location"; + conn->location.value = loc; + conn->location.static_name = true; + conn->location.static_value = static_value; + nni_list_prepend(&conn->res.data.hdrs, &conn->location); return (http_conn_set_error(conn, status, reason, NULL, redirect)); } @@ -1092,13 +1112,13 @@ nni_http_set_host(nng_http *conn, const char *host) if (host != conn->host) { snprintf(conn->host, sizeof(conn->host), "%s", host); } - nni_list_node_remove(&conn->req.host_header.node); - conn->req.host_header.name = "Host"; - conn->req.host_header.value = conn->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.data.hdrs, &conn->req.host_header); + nni_list_node_remove(&conn->host_header.node); + conn->host_header.name = "Host"; + conn->host_header.value = conn->host; + conn->host_header.static_name = true; + conn->host_header.static_value = true; + conn->host_header.alloc_header = false; + nni_list_prepend(&conn->req.data.hdrs, &conn->host_header); } void diff --git a/src/supplemental/http/http_msg.c b/src/supplemental/http/http_msg.c index 009c8ab41..8c62fb5f4 100644 --- a/src/supplemental/http/http_msg.c +++ b/src/supplemental/http/http_msg.c @@ -126,12 +126,6 @@ nni_http_res_alloc_data(nni_http_res *res, size_t size) return (0); } -bool -nni_http_res_is_error(nni_http_res *res) -{ - return (res->iserr); -} - static int http_parse_header(nng_http *conn, void *line) { diff --git a/src/supplemental/http/http_msg.h b/src/supplemental/http/http_msg.h index 5a13c409f..4b4e03a65 100644 --- a/src/supplemental/http/http_msg.h +++ b/src/supplemental/http/http_msg.h @@ -31,7 +31,6 @@ 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 clen[24]; // 64-bit lengths, in decimal char ctype[128]; // 63+63+; per RFC 6838 http_header content_type; @@ -40,17 +39,15 @@ typedef struct nni_http_entity { char *buf; size_t bufsz; bool parsed; + bool own; // if true, data is "ours", and should be freed } nni_http_entity; struct nng_http_req { nni_http_entity data; - http_header host_header; }; struct nng_http_res { nni_http_entity data; - bool iserr; - http_header location; }; 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 ffb014490..bec0c01a2 100644 --- a/src/supplemental/http/http_server.c +++ b/src/supplemental/http/http_server.c @@ -714,7 +714,6 @@ http_sconn_cbdone(void *arg) { http_sconn *sc = arg; nni_aio *aio = &sc->cbaio; - nni_http_res *res; nni_http_handler *h; nni_http_server *s = sc->server; @@ -741,7 +740,6 @@ http_sconn_cbdone(void *arg) http_sconn_close(sc); return; } - res = nni_http_conn_res(sc->conn); if (!nni_http_res_sent(sc->conn)) { const char *val; const char *method; @@ -759,7 +757,7 @@ http_sconn_cbdone(void *arg) status <= 299) { // prune off data, preserving content-length header. nni_http_prune_body(sc->conn); - } else if (nni_http_res_is_error(res)) { + } else if (nni_http_is_error(sc->conn)) { (void) nni_http_server_error(s, sc->conn); } nni_http_write_res(sc->conn, &sc->txaio);