aboutsummaryrefslogtreecommitdiff
path: root/src/supplemental/websocket/websocket.c
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2025-01-06 15:20:09 -0800
committerGarrett D'Amore <garrett@damore.org>2025-01-09 23:22:56 -0800
commit73f50e2679525e7df8734c875a3c12732565f953 (patch)
tree23bd167dfcd95305b58a29c142b51879011f63b2 /src/supplemental/websocket/websocket.c
parenta381af4f5ca79576a4a9b461529a0f22fcf1e088 (diff)
downloadnng-2.0.0-alpha.3.tar.gz
nng-2.0.0-alpha.3.tar.bz2
nng-2.0.0-alpha.3.zip
http: The big HTTP API refactoring of January 2025.v2.0.0-alpha.3http-client-trans
This represents a major change in the HTTP code base, consisting of a complete revamp of the HTTP API. The changes here are too numerous to mention, but the end result should be a vastly simpler API for both server and client applications. Many needless allocations were removed by providing fixed buffers for various parameters and headers when possible. A few bugs were fixed. Most especially we have fixed some bugs around very large URIs and headers, and we have also addressed conformance bugs to more closely conform to RFCs 9110 and 9112. As part of this work, the APIs for WebSockets changed slightly as well. In particular the properties available for accessing headers have changed. There is still documentation conversion work to do, and additional functionality (such as proper support for chunked transfers), but this is a big step in the right direction.
Diffstat (limited to 'src/supplemental/websocket/websocket.c')
-rw-r--r--src/supplemental/websocket/websocket.c348
1 files changed, 98 insertions, 250 deletions
diff --git a/src/supplemental/websocket/websocket.c b/src/supplemental/websocket/websocket.c
index 70323b0c..86edf123 100644
--- a/src/supplemental/websocket/websocket.c
+++ b/src/supplemental/websocket/websocket.c
@@ -14,6 +14,7 @@
#include <string.h>
#include "core/nng_impl.h"
+#include "nng/http.h"
#include "supplemental/http/http_api.h"
#include "base64.h"
@@ -21,7 +22,7 @@
#include "websocket.h"
// This should be removed or handled differently in the future.
-typedef int (*nni_ws_listen_hook)(void *, nng_http_req *, nng_http_res *);
+typedef int (*nni_ws_listen_hook)(void *, nng_http *);
// We have chosen to be a bit more stringent in the size of the frames that
// we send, while we more generously allow larger incoming frames. These
@@ -55,6 +56,7 @@ struct nni_ws {
bool inmsg;
bool send_text;
bool recv_text;
+ bool recv_res;
nni_mtx mtx;
nni_list sendq;
nni_list recvq;
@@ -68,16 +70,21 @@ struct nni_ws {
nni_aio httpaio;
nni_aio connaio; // connect aio
nni_aio *useraio; // user aio, during HTTP negotiation
- nni_http_conn *http;
- nni_http_req *req;
- nni_http_res *res;
- char *reqhdrs;
- char *reshdrs;
+ nng_http *http;
size_t maxframe;
size_t fragsize;
size_t recvmax; // largest message size
nni_ws_listener *listener;
nni_ws_dialer *dialer;
+ char keybuf[29]; // key on client, accept on server
+ struct {
+ nni_http_header connection;
+ nni_http_header upgrade;
+ nni_http_header wsaccept;
+ nni_http_header wskey;
+ nni_http_header wsproto;
+ nni_http_header wsversion;
+ } hdrs;
};
struct nni_ws_listener {
@@ -235,64 +242,6 @@ ws_set_header(nni_list *l, const char *n, const char *v)
return (ws_set_header_ext(l, n, v, true));
}
-static int
-ws_set_headers(nni_list *l, const char *str)
-{
- char *dupstr;
- size_t duplen;
- char *n;
- char *v;
- char *nl;
- int rv;
-
- if ((dupstr = nni_strdup(str)) == NULL) {
- return (NNG_ENOMEM);
- }
- duplen = strlen(dupstr) + 1; // so we can free it later
-
- n = dupstr;
- for (;;) {
- if ((v = strchr(n, ':')) == NULL) {
- // Note that this also means that if
- // a bare word is present, we ignore it.
- break;
- }
- *v = '\0';
- v++;
- while (*v == ' ') {
- // Skip leading whitespace. Not strictly
- // necessary, but still a good idea.
- v++;
- }
- nl = v;
- // Find the end of the line -- should be CRLF, but can
- // also be unterminated or just LF if user
- while ((*nl != '\0') && (*nl != '\r') && (*nl != '\n')) {
- nl++;
- }
- while ((*nl == '\r') || (*nl == '\n')) {
- *nl = '\0';
- nl++;
- }
-
- // Note that this can lead to a partial failure. As this
- // is most likely ENOMEM, don't worry too much about it.
- // This method does *not* eliminate duplicates.
- if ((rv = ws_set_header_ext(l, n, v, false)) != 0) {
- goto done;
- }
-
- // Advance to the next name.
- n = nl;
- }
-
- rv = 0;
-
-done:
- nni_free(dupstr, duplen);
- return (rv);
-}
-
// This looks, case independently for a word in a list, which is either
// space or comma separated.
static bool
@@ -1244,8 +1193,6 @@ ws_fini(void *arg)
nni_http_conn_fini(ws->http);
}
- nni_strfree(ws->reqhdrs);
- nni_strfree(ws->reshdrs);
nni_aio_fini(&ws->rxaio);
nni_aio_fini(&ws->txaio);
nni_aio_fini(&ws->closeaio);
@@ -1325,14 +1272,14 @@ ws_http_cb_dialer(nni_ws *ws, nni_aio *aio)
// If we have no response structure, then this was completion
// of sending the request. Prepare an empty response, and read it.
- if (ws->res == NULL) {
- ws->res = nni_http_conn_res(ws->http);
- nni_http_read_res(ws->http, ws->res, &ws->httpaio);
+ if (!ws->recv_res) {
+ ws->recv_res = true;
+ nng_http_read_response(ws->http, &ws->httpaio);
nni_mtx_unlock(&d->mtx);
return;
}
- status = nni_http_res_get_status(ws->res);
+ status = nni_http_get_status(ws->http);
switch (status) {
case NNG_HTTP_STATUS_SWITCHING:
break;
@@ -1342,6 +1289,7 @@ ws_http_cb_dialer(nni_ws *ws, nni_aio *aio)
goto err;
case NNG_HTTP_STATUS_NOT_FOUND:
case NNG_HTTP_STATUS_METHOD_NOT_ALLOWED:
+ case NNG_HTTP_STATUS_NOT_IMPLEMENTED:
rv = NNG_ECONNREFUSED; // Treat these as refusals.
goto err;
case NNG_HTTP_STATUS_BAD_REQUEST:
@@ -1351,34 +1299,31 @@ ws_http_cb_dialer(nni_ws *ws, nni_aio *aio)
goto err;
}
- // Check that the server gave us back the right key.
- rv = ws_make_accept(
- nni_http_req_get_header(ws->req, "Sec-WebSocket-Key"), wskey);
+ rv = ws_make_accept(ws->keybuf, wskey);
if (rv != 0) {
goto err;
}
-#define GETH(h) nni_http_res_get_header(ws->res, h)
-
- if (((ptr = GETH("Sec-WebSocket-Accept")) == NULL) ||
+ if (((ptr = nng_http_get_header(ws->http, "Sec-WebSocket-Accept")) ==
+ NULL) ||
(strcmp(ptr, wskey) != 0) ||
- ((ptr = GETH("Connection")) == NULL) ||
+ ((ptr = nng_http_get_header(ws->http, "Connection")) == NULL) ||
(!ws_contains_word(ptr, "upgrade")) ||
- ((ptr = GETH("Upgrade")) == NULL) ||
+ ((ptr = nng_http_get_header(ws->http, "Upgrade")) == NULL) ||
(strcmp(ptr, "websocket") != 0)) {
ws_close_error(ws, WS_CLOSE_PROTOCOL_ERR);
rv = NNG_EPROTO;
goto err;
}
if (d->proto != NULL) {
- if (((ptr = GETH("Sec-WebSocket-Protocol")) == NULL) ||
+ if (((ptr = nng_http_get_header(
+ ws->http, "Sec-WebSocket-Protocol")) == NULL) ||
(!ws_contains_word(d->proto, ptr))) {
ws_close_error(ws, WS_CLOSE_PROTOCOL_ERR);
rv = NNG_EPROTO;
goto err;
}
}
-#undef GETH
// At this point, we are in business!
nni_list_remove(&d->wspend, ws);
@@ -1506,19 +1451,16 @@ ws_listener_free(void *arg)
}
static void
-ws_handler(nng_http_conn *conn, void *arg, nng_aio *aio)
+ws_handler(nng_http *conn, void *arg, nng_aio *aio)
{
nni_ws_listener *l = arg;
- ;
- nni_http_req *req = nng_http_conn_req(conn);
- nni_http_res *res = nng_http_conn_res(conn);
- nni_ws *ws;
- const char *ptr;
- const char *proto;
- uint16_t status;
- int rv;
- char key[29];
- ws_header *hdr;
+ nni_ws *ws;
+ const char *ptr;
+ const char *proto;
+ uint16_t status;
+ int rv;
+ char key[29];
+ ws_header *hdr;
nni_mtx_lock(&l->mtx);
if (l->closed) {
@@ -1527,39 +1469,39 @@ ws_handler(nng_http_conn *conn, void *arg, nng_aio *aio)
}
// Now check the headers, etc.
- if (strcmp(nni_http_req_get_version(req), "HTTP/1.1") != 0) {
+ if (strcmp(nng_http_get_version(conn), "HTTP/1.1") != 0) {
status = NNG_HTTP_STATUS_HTTP_VERSION_NOT_SUPP;
goto err;
}
- if (strcmp(nni_http_req_get_method(req), "GET") != 0) {
+ if (strcmp(nng_http_get_method(conn), "GET") != 0) {
// HEAD request. We can't really deal with it.
status = NNG_HTTP_STATUS_BAD_REQUEST;
goto err;
}
-#define GETH(h) nni_http_req_get_header(req, h)
-#define SETH(h, v) nni_http_res_set_header(res, h, v)
-
- if ((((ptr = GETH("Content-Length")) != NULL) && (atoi(ptr) > 0)) ||
- (((ptr = GETH("Transfer-Encoding")) != NULL) &&
+ if ((((ptr = nng_http_get_header(conn, "Content-Length")) != NULL) &&
+ (atoi(ptr) > 0)) ||
+ (((ptr = nng_http_get_header(conn, "Transfer-Encoding")) !=
+ NULL) &&
(nni_strcasestr(ptr, "chunked") != NULL))) {
- status = NNG_HTTP_STATUS_PAYLOAD_TOO_LARGE;
+ status = NNG_HTTP_STATUS_CONTENT_TOO_LARGE;
goto err;
}
// These headers have to be present.
- if (((ptr = GETH("Upgrade")) == NULL) ||
+ if (((ptr = nng_http_get_header(conn, "Upgrade")) == NULL) ||
(!ws_contains_word(ptr, "websocket")) ||
- ((ptr = GETH("Connection")) == NULL) ||
+ ((ptr = nng_http_get_header(conn, "Connection")) == NULL) ||
(!ws_contains_word(ptr, "upgrade")) ||
- ((ptr = GETH("Sec-WebSocket-Version")) == NULL) ||
+ ((ptr = nng_http_get_header(conn, "Sec-WebSocket-Version")) ==
+ NULL) ||
(strcmp(ptr, "13") != 0)) {
status = NNG_HTTP_STATUS_BAD_REQUEST;
goto err;
}
- if (((ptr = GETH("Sec-WebSocket-Key")) == NULL) ||
+ if (((ptr = nng_http_get_header(conn, "Sec-WebSocket-Key")) == NULL) ||
(ws_make_accept(ptr, key) != 0)) {
status = NNG_HTTP_STATUS_BAD_REQUEST;
goto err;
@@ -1569,7 +1511,7 @@ ws_handler(nng_http_conn *conn, void *arg, nng_aio *aio)
// we need to try to match it to what the handler says we
// support. (If no suitable option is found in the handler, we
// fail the request.)
- proto = GETH("Sec-WebSocket-Protocol");
+ proto = nng_http_get_header(conn, "Sec-WebSocket-Protocol");
if (proto == NULL) {
if (l->proto != NULL) {
status = NNG_HTTP_STATUS_BAD_REQUEST;
@@ -1581,23 +1523,13 @@ ws_handler(nng_http_conn *conn, void *arg, nng_aio *aio)
goto err;
}
- nni_http_res_set_status(res, NNG_HTTP_STATUS_SWITCHING);
-
- if ((SETH("Connection", "Upgrade") != 0) ||
- (SETH("Upgrade", "websocket") != 0) ||
- (SETH("Sec-WebSocket-Accept", key) != 0)) {
- status = NNG_HTTP_STATUS_INTERNAL_SERVER_ERROR;
- goto err;
- }
- if ((proto != NULL) && (SETH("Sec-WebSocket-Protocol", proto) != 0)) {
- status = NNG_HTTP_STATUS_INTERNAL_SERVER_ERROR;
- goto err;
- }
+ nng_http_set_status(conn, NNG_HTTP_STATUS_SWITCHING, NULL);
// Set any user supplied headers. This is better than using a hook
- // for most things, because it is loads easier.
+ // for most things, because it is loads easier. Note that websocket
+ // headers we care about will be overridden below!
NNI_LIST_FOREACH (&l->headers, hdr) {
- if (SETH(hdr->name, hdr->value) != 0) {
+ if (nng_http_set_header(conn, hdr->name, hdr->value) != 0) {
status = NNG_HTTP_STATUS_INTERNAL_SERVER_ERROR;
goto err;
}
@@ -1608,33 +1540,25 @@ ws_handler(nng_http_conn *conn, void *arg, nng_aio *aio)
// need to, because it's much more complex. But if you want to set
// up an HTTP Authorization handler this might be the only choice.
if (l->hookfn != NULL) {
- rv = l->hookfn(l->hookarg, req, res);
+ rv = l->hookfn(l->hookarg, conn);
if (rv != 0) {
nni_aio_finish_error(aio, rv);
nni_mtx_unlock(&l->mtx);
return;
}
- if (nni_http_res_get_status(res) !=
- NNG_HTTP_STATUS_SWITCHING) {
+ if (nng_http_get_status(conn) != NNG_HTTP_STATUS_SWITCHING) {
// The hook has decided to give back a
// different reply and we are not upgrading
// anymore. For example the Origin might not
// be permitted, or another level of
- // authentication may be required. (Note that
- // the hook can also give back various other
- // headers, but it would be bad for it to alter
- // the websocket mandated headers.)
- nni_aio_set_output(aio, 0, res);
+ // authentication may be required.
nni_aio_finish(aio, 0, 0);
nni_mtx_unlock(&l->mtx);
return;
}
}
-#undef GETH
-#undef SETH
-
// We are good to go, provided we can get the websocket struct,
// and send the reply.
if ((rv = ws_init(&ws)) != 0) {
@@ -1642,8 +1566,6 @@ ws_handler(nng_http_conn *conn, void *arg, nng_aio *aio)
goto err;
}
ws->http = conn;
- ws->req = req;
- ws->res = res;
ws->server = true;
ws->maxframe = l->maxframe;
ws->fragsize = l->fragsize;
@@ -1652,9 +1574,23 @@ ws_handler(nng_http_conn *conn, void *arg, nng_aio *aio)
ws->recv_text = l->recv_text;
ws->send_text = l->send_text;
ws->listener = l;
+ memcpy(ws->keybuf, key, sizeof(ws->keybuf));
+
+ nni_http_set_static_header(
+ conn, &ws->hdrs.connection, "Connection", "Upgrade");
+ nni_http_set_static_header(
+ conn, &ws->hdrs.upgrade, "Upgrade", "websocket");
+ nni_http_set_static_header(
+ conn, &ws->hdrs.wsaccept, "Sec-WebSocket-Accept", ws->keybuf);
+ if (proto != NULL) {
+ // NB: we still have the request protocol in the header, so
+ // that should be fine.
+ nni_http_set_static_header(
+ conn, &ws->hdrs.wsproto, "Sec-WebSocket-Protocol", proto);
+ }
nni_list_append(&l->reply, ws);
- nni_http_write_res(conn, &ws->httpaio);
+ nng_http_write_response(conn, &ws->httpaio);
(void) nni_http_hijack(conn);
nni_aio_set_output(aio, 0, NULL);
nni_aio_finish(aio, 0, 0);
@@ -1662,10 +1598,9 @@ ws_handler(nng_http_conn *conn, void *arg, nng_aio *aio)
return;
err:
- if ((rv = nni_http_res_set_error(res, status)) != 0) {
+ if ((rv = nni_http_set_error(conn, status, NULL, NULL)) != 0) {
nni_aio_finish_error(aio, rv);
} else {
- nni_aio_set_output(aio, 0, res);
nni_aio_finish(aio, 0, 0);
}
nni_mtx_unlock(&l->mtx);
@@ -1862,20 +1797,6 @@ ws_listener_get_recvmax(void *arg, void *buf, size_t *szp, nni_type t)
}
static int
-ws_listener_set_res_headers(void *arg, const void *buf, size_t sz, nni_type t)
-{
- nni_ws_listener *l = arg;
- int rv;
-
- if ((rv = ws_check_string(buf, sz, t)) == 0) {
- nni_mtx_lock(&l->mtx);
- rv = ws_set_headers(&l->headers, buf);
- nni_mtx_unlock(&l->mtx);
- }
- return (rv);
-}
-
-static int
ws_listener_set_proto(void *arg, const void *buf, size_t sz, nni_type t)
{
nni_ws_listener *l = arg;
@@ -1996,11 +1917,6 @@ static const nni_option ws_listener_options[] = {
.o_get = ws_listener_get_recvmax,
},
{
- .o_name = NNG_OPT_WS_RESPONSE_HEADERS,
- .o_set = ws_listener_set_res_headers,
- // XXX: Get not implemented yet; likely of marginal value.
- },
- {
.o_name = NNG_OPT_WS_PROTOCOL,
.o_set = ws_listener_set_proto,
.o_get = ws_listener_get_proto,
@@ -2025,7 +1941,7 @@ ws_listener_set_header(nni_ws_listener *l, const char *name, const void *buf,
size_t sz, nni_type t)
{
int rv;
- name += strlen(NNG_OPT_WS_RESPONSE_HEADER);
+ name += strlen(NNG_OPT_WS_HEADER);
if ((rv = ws_check_string(buf, sz, t)) == 0) {
nni_mtx_lock(&l->mtx);
rv = ws_set_header(&l->headers, name, buf);
@@ -2047,7 +1963,7 @@ ws_listener_set(
}
if (rv == NNG_ENOTSUP) {
- if (startswith(name, NNG_OPT_WS_RESPONSE_HEADER)) {
+ if (startswith(name, NNG_OPT_WS_HEADER)) {
rv = ws_listener_set_header(l, name, buf, sz, t);
}
}
@@ -2147,10 +2063,8 @@ ws_conn_cb(void *arg)
nni_ws_dialer *d;
nni_ws *ws;
nni_aio *uaio;
- nni_http_req *req = NULL;
int rv;
uint8_t raw[16];
- char wskey[25];
ws_header *hdr;
ws = arg;
@@ -2192,35 +2106,36 @@ ws_conn_cb(void *arg)
for (int i = 0; i < 16; i++) {
raw[i] = (uint8_t) nni_random();
}
- nni_base64_encode(raw, 16, wskey, 24);
- wskey[24] = '\0';
-
- req = nni_http_conn_req(ws->http);
+ nni_base64_encode(raw, 16, ws->keybuf, 24);
+ ws->keybuf[24] = '\0';
-#define SETH(h, v) nni_http_req_set_header(req, h, v)
- if ((rv != 0) || ((rv = nni_http_req_set_url(req, d->url)) != 0) ||
- ((rv = SETH("Upgrade", "websocket")) != 0) ||
- ((rv = SETH("Connection", "Upgrade")) != 0) ||
- ((rv = SETH("Sec-WebSocket-Key", wskey)) != 0) ||
- ((rv = SETH("Sec-WebSocket-Version", "13")) != 0)) {
+ if ((rv = nni_http_set_uri(
+ ws->http, d->url->u_path, d->url->u_query)) != 0) {
goto err;
}
- if ((d->proto != NULL) &&
- ((rv = SETH("Sec-WebSocket-Protocol", d->proto)) != 0)) {
- goto err;
+ nni_http_set_static_header(
+ ws->http, &ws->hdrs.connection, "Connection", "Upgrade");
+ nni_http_set_static_header(
+ ws->http, &ws->hdrs.upgrade, "Upgrade", "websocket");
+ nni_http_set_static_header(
+ ws->http, &ws->hdrs.wskey, "Sec-WebSocket-Key", ws->keybuf);
+ nni_http_set_static_header(
+ ws->http, &ws->hdrs.wsversion, "Sec-WebSocket-Version", "13");
+
+ if (d->proto != NULL) {
+ nni_http_set_static_header(ws->http, &ws->hdrs.wsproto,
+ "Sec-WebSocket-Protocol", d->proto);
}
NNI_LIST_FOREACH (&d->headers, hdr) {
- if ((rv = SETH(hdr->name, hdr->value)) != 0) {
+ if ((rv = nni_http_set_header(
+ ws->http, hdr->name, hdr->value)) != 0) {
goto err;
}
}
-#undef SETH
-
- ws->req = req;
- nni_http_write_req(ws->http, req, &ws->httpaio);
+ nni_http_write_req(ws->http, &ws->httpaio);
nni_mtx_unlock(&ws->mtx);
return;
@@ -2455,20 +2370,6 @@ ws_dialer_get_recvmax(void *arg, void *buf, size_t *szp, nni_type t)
}
static int
-ws_dialer_set_req_headers(void *arg, const void *buf, size_t sz, nni_type t)
-{
- nni_ws_dialer *d = arg;
- int rv;
-
- if ((rv = ws_check_string(buf, sz, t)) == 0) {
- nni_mtx_lock(&d->mtx);
- rv = ws_set_headers(&d->headers, buf);
- nni_mtx_unlock(&d->mtx);
- }
- return (rv);
-}
-
-static int
ws_dialer_set_proto(void *arg, const void *buf, size_t sz, nni_type t)
{
nni_ws_dialer *d = arg;
@@ -2544,11 +2445,6 @@ static const nni_option ws_dialer_options[] = {
.o_get = ws_dialer_get_recvmax,
},
{
- .o_name = NNG_OPT_WS_REQUEST_HEADERS,
- .o_set = ws_dialer_set_req_headers,
- // XXX: Get not implemented yet; likely of marginal value.
- },
- {
.o_name = NNG_OPT_WS_PROTOCOL,
.o_set = ws_dialer_set_proto,
.o_get = ws_dialer_get_proto,
@@ -2574,7 +2470,7 @@ ws_dialer_set_header(
nni_ws_dialer *d, const char *name, const void *buf, size_t sz, nni_type t)
{
int rv;
- name += strlen(NNG_OPT_WS_REQUEST_HEADER);
+ name += strlen(NNG_OPT_WS_HEADER);
if ((rv = ws_check_string(buf, sz, t)) == 0) {
nni_mtx_lock(&d->mtx);
rv = ws_set_header(&d->headers, name, buf);
@@ -2596,7 +2492,7 @@ ws_dialer_set(
}
if (rv == NNG_ENOTSUP) {
- if (startswith(name, NNG_OPT_WS_REQUEST_HEADER)) {
+ if (startswith(name, NNG_OPT_WS_HEADER)) {
rv = ws_dialer_set_header(d, name, buf, sz, t);
}
}
@@ -2773,34 +2669,10 @@ ws_str_recv(void *arg, nng_aio *aio)
}
static int
-ws_get_request_headers(void *arg, void *buf, size_t *szp, nni_type t)
-{
- nni_ws *ws = arg;
- nni_mtx_lock(&ws->mtx);
- if (ws->reqhdrs == NULL) {
- ws->reqhdrs = nni_http_req_headers(ws->req);
- }
- nni_mtx_unlock(&ws->mtx);
- return (nni_copyout_str(ws->reqhdrs, buf, szp, t));
-}
-
-static int
-ws_get_response_headers(void *arg, void *buf, size_t *szp, nni_type t)
-{
- nni_ws *ws = arg;
- nni_mtx_lock(&ws->mtx);
- if (ws->reshdrs == NULL) {
- ws->reshdrs = nni_http_res_headers(ws->res);
- }
- nni_mtx_unlock(&ws->mtx);
- return (nni_copyout_str(ws->reshdrs, buf, szp, t));
-}
-
-static int
ws_get_request_uri(void *arg, void *buf, size_t *szp, nni_type t)
{
nni_ws *ws = arg;
- return (nni_copyout_str(nni_http_req_get_uri(ws->req), buf, szp, t));
+ return (nni_copyout_str(nni_http_get_uri(ws->http), buf, szp, t));
}
static int
@@ -2829,14 +2701,6 @@ ws_get_send_text(void *arg, void *buf, size_t *szp, nni_type t)
static const nni_option ws_options[] = {
{
- .o_name = NNG_OPT_WS_REQUEST_HEADERS,
- .o_get = ws_get_request_headers,
- },
- {
- .o_name = NNG_OPT_WS_RESPONSE_HEADERS,
- .o_get = ws_get_response_headers,
- },
- {
.o_name = NNG_OPT_WS_REQUEST_URI,
.o_get = ws_get_request_uri,
},
@@ -2854,25 +2718,11 @@ static const nni_option ws_options[] = {
};
static int
-ws_get_req_header(
- nni_ws *ws, const char *nm, void *buf, size_t *szp, nni_type t)
-{
- const char *s;
- nm += strlen(NNG_OPT_WS_REQUEST_HEADER);
- s = nni_http_req_get_header(ws->req, nm);
- if (s == NULL) {
- return (NNG_ENOENT);
- }
- return (nni_copyout_str(s, buf, szp, t));
-}
-
-static int
-ws_get_res_header(
- nni_ws *ws, const char *nm, void *buf, size_t *szp, nni_type t)
+ws_get_header(nni_ws *ws, const char *nm, void *buf, size_t *szp, nni_type t)
{
const char *s;
- nm += strlen(NNG_OPT_WS_RESPONSE_HEADER);
- s = nni_http_res_get_header(ws->res, nm);
+ nm += strlen(NNG_OPT_WS_HEADER);
+ s = nni_http_get_header(ws->http, nm);
if (s == NULL) {
return (NNG_ENOENT);
}
@@ -2897,10 +2747,8 @@ ws_str_get(void *arg, const char *nm, void *buf, size_t *szp, nni_type t)
}
// Check for generic headers...
if (rv == NNG_ENOTSUP) {
- if (startswith(nm, NNG_OPT_WS_REQUEST_HEADER)) {
- rv = ws_get_req_header(ws, nm, buf, szp, t);
- } else if (startswith(nm, NNG_OPT_WS_RESPONSE_HEADER)) {
- rv = ws_get_res_header(ws, nm, buf, szp, t);
+ if (startswith(nm, NNG_OPT_WS_HEADER)) {
+ rv = ws_get_header(ws, nm, buf, szp, t);
}
}
return (rv);