aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2025-01-12 08:28:03 -0800
committerGarrett D'Amore <garrett@damore.org>2025-01-12 08:28:03 -0800
commit4f445061dc9dbc1e437ff04eff6f39f021bd5bec (patch)
treeab3f0fcb11b3b36b7081580618d7b7d0bfda0731
parentd87b873ea5bbdae1352b2a61f5110f20b65928cc (diff)
downloadnng-4f445061dc9dbc1e437ff04eff6f39f021bd5bec.tar.gz
nng-4f445061dc9dbc1e437ff04eff6f39f021bd5bec.tar.bz2
nng-4f445061dc9dbc1e437ff04eff6f39f021bd5bec.zip
http: move connection properties to http_conn, use static Location for redirect
-rw-r--r--src/supplemental/http/http_api.h2
-rw-r--r--src/supplemental/http/http_conn.c82
-rw-r--r--src/supplemental/http/http_msg.c6
-rw-r--r--src/supplemental/http/http_msg.h5
-rw-r--r--src/supplemental/http/http_server.c4
5 files changed, 54 insertions, 45 deletions
diff --git a/src/supplemental/http/http_api.h b/src/supplemental/http/http_api.h
index 02b5fbe4..c8d73788 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 824baa96..65c240f5 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,
"<h2>%s</h2><p>";
const char *suffix = "</p></body></html>";
- 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 009c8ab4..8c62fb5f 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 5a13c409..4b4e03a6 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 ffb01449..bec0c01a 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);