diff --git a/docs/man/nng_http_req_set_version.3http.adoc b/docs/man/nng_http_req_set_version.3http.adoc index 04fd1b0d9..ca41f0ef5 100644 --- a/docs/man/nng_http_req_set_version.3http.adoc +++ b/docs/man/nng_http_req_set_version.3http.adoc @@ -1,6 +1,6 @@ = nng_http_req_set_version(3http) // -// Copyright 2018 Staysail Systems, Inc. +// Copyright 2024 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV // // This document is supplied under the terms of the MIT License, a @@ -20,6 +20,9 @@ nng_http_req_set_version - set HTTP request protocol version #include #include +#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); ---- @@ -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 @@ -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 diff --git a/docs/man/nng_http_res_set_version.3http.adoc b/docs/man/nng_http_res_set_version.3http.adoc index 23c25312b..47ce3cd7e 100644 --- a/docs/man/nng_http_res_set_version.3http.adoc +++ b/docs/man/nng_http_res_set_version.3http.adoc @@ -1,6 +1,6 @@ = nng_http_res_set_version(3http) // -// Copyright 2018 Staysail Systems, Inc. +// Copyright 2024 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV // // This document is supplied under the terms of the MIT License, a @@ -20,6 +20,9 @@ nng_http_res_set_version - set HTTP response protocol version #include #include +#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); ---- @@ -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 @@ -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 diff --git a/include/nng/supplemental/http/http.h b/include/nng/supplemental/http/http.h index fa81f984d..bb163949a 100644 --- a/include/nng/supplemental/http/http.h +++ b/include/nng/supplemental/http/http.h @@ -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; diff --git a/src/supplemental/http/http_msg.c b/src/supplemental/http/http_msg.c index 670fb28ea..afe2a3b64 100644 --- a/src/supplemental/http/http_msg.c +++ b/src/supplemental/http/http_msg.c @@ -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 @@ -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; @@ -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; @@ -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 @@ -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; @@ -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); } @@ -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); } @@ -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) { @@ -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; @@ -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); +} + +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); } 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