Skip to content

Commit

Permalink
HTTP: intern the version and avoid allocation
Browse files Browse the repository at this point in the history
There are only a few possible reasonable values, and we can intern
them to avoid any allocations for it.  (We will probably do the same
for the HTTP method shortly as well.)
  • Loading branch information
gdamore committed Dec 22, 2024
1 parent f0e0801 commit 9ac2c5a
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 33 deletions.
11 changes: 5 additions & 6 deletions docs/man/nng_http_req_set_version.3http.adoc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
= nng_http_req_set_version(3http)
//
// Copyright 2018 Staysail Systems, Inc. <[email protected]>
// Copyright 2024 Staysail Systems, Inc. <[email protected]>
// Copyright 2018 Capitar IT Group BV <[email protected]>
//
// This document is supplied under the terms of the MIT License, a
Expand All @@ -20,6 +20,9 @@ nng_http_req_set_version - set HTTP request protocol version
#include <nng/nng.h>
#include <nng/supplemental/http/http.h>
#define NNG_HTTP_VERSION_1_1 "HTTP/1.0"
#define NNG_HTTP_VERSION_1_1 "HTTP/1.1"
int nng_http_req_set_version(nng_http_req *req, const char *version);
----

Expand All @@ -33,12 +36,8 @@ The default value is "HTTP/1.1".

A local copy of the _version_ is made in the request _req_.

NOTE: No validation of the version supplied is performed.

NOTE: The library does not contain support for versions of HTTP other than
"HTTP/1.0" and "HTTP/1.1".
Specifying any other version may result in unspecified behavior.


== RETURN VALUES

Expand All @@ -48,7 +47,7 @@ This function returns 0 on success, and non-zero otherwise.

[horizontal]
`NNG_ENOMEM`:: Insufficient memory to perform the operation.
`NNG_ENOTSUP`:: No support for HTTP in the library.
`NNG_ENOTSUP`:: No support for HTTP in the library, or no support for the version specified.

== SEE ALSO

Expand Down
11 changes: 5 additions & 6 deletions docs/man/nng_http_res_set_version.3http.adoc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
= nng_http_res_set_version(3http)
//
// Copyright 2018 Staysail Systems, Inc. <[email protected]>
// Copyright 2024 Staysail Systems, Inc. <[email protected]>
// Copyright 2018 Capitar IT Group BV <[email protected]>
//
// This document is supplied under the terms of the MIT License, a
Expand All @@ -20,6 +20,9 @@ nng_http_res_set_version - set HTTP response protocol version
#include <nng/nng.h>
#include <nng/supplemental/http/http.h>
#define NNG_HTTP_VERSION_1_1 "HTTP/1.0"
#define NNG_HTTP_VERSION_1_1 "HTTP/1.1"
int nng_http_res_set_version(nng_http_res *res, const char *version);
----

Expand All @@ -33,12 +36,8 @@ The default value is "HTTP/1.1".

A local copy of the _version_ is made in the response _res_.

NOTE: No validation of the version supplied is performed.

NOTE: The library does not contain support for versions of HTTP other than
"HTTP/1.0" and "HTTP/1.1".
Specifying any other version may result in unspecified behavior.


== RETURN VALUES

Expand All @@ -48,7 +47,7 @@ This function returns 0 on success, and non-zero otherwise.

[horizontal]
`NNG_ENOMEM`:: Insufficient memory to perform the operation.
`NNG_ENOTSUP`:: No support for HTTP in the library.
`NNG_ENOTSUP`:: No support for HTTP in the library, or no support for the version specified.

== SEE ALSO

Expand Down
5 changes: 5 additions & 0 deletions include/nng/supplemental/http/http.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ enum nng_http_status {
NNG_HTTP_STATUS_NETWORK_AUTH_REQUIRED = 511,
};

#define NNG_HTTP_VERSION_1_0 "HTTP/1.0"
#define NNG_HTTP_VERSION_1_1 "HTTP/1.1"
#define NNG_HTTP_VERSION_2 "HTTP/2"
#define NNG_HTTP_VERSION_3 "HTTP/3"

// nng_http_req represents an HTTP request.
typedef struct nng_http_req nng_http_req;

Expand Down
58 changes: 37 additions & 21 deletions src/supplemental/http/http_msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include "core/nng_impl.h"
#include "http_api.h"
#include "nng/supplemental/http/http.h"

// Note that as we parse headers, the rule is that if a header is already
// present, then we can append it to the existing header, separated by
Expand All @@ -39,7 +40,7 @@ struct nng_http_req {
nni_http_entity data;
char *meth;
char *uri;
char *vers;
const char *vers;
char *buf;
size_t bufsz;
bool parsed;
Expand All @@ -50,7 +51,7 @@ struct nng_http_res {
nni_http_entity data;
uint16_t code;
char *rsn;
char *vers;
const char *vers;
char *buf;
size_t bufsz;
bool parsed;
Expand Down Expand Up @@ -99,14 +100,14 @@ nni_http_req_reset(nni_http_req *req)
{
http_headers_reset(&req->hdrs);
http_entity_reset(&req->data);
nni_strfree(req->vers);
nni_strfree(req->meth);
nni_strfree(req->uri);
req->vers = req->meth = req->uri = NULL;
req->meth = req->uri = NULL;
nni_free(req->buf, req->bufsz);
req->bufsz = 0;
req->buf = NULL;
req->parsed = false;
req->vers = NNG_HTTP_VERSION_1_1;
}

void
Expand All @@ -115,8 +116,7 @@ nni_http_res_reset(nni_http_res *res)
http_headers_reset(&res->hdrs);
http_entity_reset(&res->data);
nni_strfree(res->rsn);
nni_strfree(res->vers);
res->vers = NULL;
res->vers = NNG_HTTP_VERSION_1_1;
res->rsn = NULL;
res->code = 0;
res->parsed = false;
Expand Down Expand Up @@ -532,8 +532,7 @@ http_req_prepare(nni_http_req *req)
return (NNG_EINVAL);
}
rv = http_asprintf(&req->buf, &req->bufsz, &req->hdrs, "%s %s %s\r\n",
req->meth != NULL ? req->meth : "GET", req->uri,
req->vers != NULL ? req->vers : "HTTP/1.1");
req->meth != NULL ? req->meth : "GET", req->uri, req->vers);
return (rv);
}

Expand All @@ -542,7 +541,7 @@ http_res_prepare(nni_http_res *res)
{
int rv;
rv = http_asprintf(&res->buf, &res->bufsz, &res->hdrs, "%s %d %s\r\n",
nni_http_res_get_version(res), nni_http_res_get_status(res),
res->vers, nni_http_res_get_status(res),
nni_http_res_get_reason(res));
return (rv);
}
Expand Down Expand Up @@ -612,7 +611,7 @@ nni_http_req_alloc(nni_http_req **reqp, const nng_url *url)
req->data.data = NULL;
req->data.size = 0;
req->data.own = false;
req->vers = NULL;
req->vers = NNG_HTTP_VERSION_1_1;
req->meth = NULL;
req->uri = NULL;
if (url != NULL) {
Expand Down Expand Up @@ -664,7 +663,7 @@ nni_http_res_alloc(nni_http_res **resp)
res->data.data = NULL;
res->data.size = 0;
res->data.own = false;
res->vers = NULL;
res->vers = NNG_HTTP_VERSION_1_1;
res->rsn = NULL;
res->code = 0;
*resp = res;
Expand All @@ -686,31 +685,48 @@ nni_http_req_get_uri(const nni_http_req *req)
const char *
nni_http_req_get_version(const nni_http_req *req)
{
return (req->vers != NULL ? req->vers : "HTTP/1.1");
return (req->vers);
}

const char *
nni_http_res_get_version(const nni_http_res *res)
{
return (res->vers != NULL ? res->vers : "HTTP/1.1");
return (res->vers);

Check warning on line 694 in src/supplemental/http/http_msg.c

View check run for this annotation

Codecov / codecov/patch

src/supplemental/http/http_msg.c#L694

Added line #L694 was not covered by tests
}

static const char *http_versions[] = {
// for efficiency, we order in most likely first
"HTTP/1.1",
"HTTP/2",
"HTTP/3",
"HTTP/1.0",
"HTTP/0.9",
NULL,
};

static int
http_set_version(const char **ptr, const char *vers)
{
vers = vers != NULL ? vers : NNG_HTTP_VERSION_1_1;
for (int i = 0; http_versions[i] != NULL; i++) {
if (strcmp(vers, http_versions[i]) == 0) {
*ptr = http_versions[i];
return (0);
}
}
return (NNG_ENOTSUP);

Check warning on line 717 in src/supplemental/http/http_msg.c

View check run for this annotation

Codecov / codecov/patch

src/supplemental/http/http_msg.c#L717

Added line #L717 was not covered by tests
}

int
nni_http_req_set_version(nni_http_req *req, const char *vers)
{
if ((vers != NULL) && (strcmp(vers, "HTTP/1.1") == 0)) {
vers = NULL;
}
return (http_set_string(&req->vers, vers));
return (http_set_version(&req->vers, vers));
}

int
nni_http_res_set_version(nni_http_res *res, const char *vers)
{
if ((vers != NULL) && (strcmp(vers, "HTTP/1.1") == 0)) {
vers = NULL;
}
return (http_set_string(&res->vers, vers));
return (http_set_version(&res->vers, vers));
}

int
Expand Down

0 comments on commit 9ac2c5a

Please sign in to comment.