aboutsummaryrefslogtreecommitdiff
path: root/src/supplemental/http/http_msg.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/supplemental/http/http_msg.c')
-rw-r--r--src/supplemental/http/http_msg.c778
1 files changed, 110 insertions, 668 deletions
diff --git a/src/supplemental/http/http_msg.c b/src/supplemental/http/http_msg.c
index 6b12496c..988bb37e 100644
--- a/src/supplemental/http/http_msg.c
+++ b/src/supplemental/http/http_msg.c
@@ -14,23 +14,27 @@
#include <stdlib.h>
#include <string.h>
+#include "core/list.h"
#include "core/nng_impl.h"
#include "http_api.h"
#include "http_msg.h"
-#include "nng/supplemental/http/http.h"
+#include "nng/http.h"
-static int
-http_set_string(char **strp, const char *val)
+void
+nni_http_free_header(http_header *h)
{
- char *news;
- if (val == NULL) {
- news = NULL;
- } else if ((news = nni_strdup(val)) == NULL) {
- return (NNG_ENOMEM);
+ nni_list_node_remove(&h->node);
+ if (!h->static_name) {
+ nni_strfree(h->name);
+ h->name = NULL;
+ }
+ if (!h->static_value) {
+ nni_strfree(h->value);
+ h->value = NULL;
+ }
+ if (h->alloc_header) {
+ NNI_FREE_STRUCT(h);
}
- nni_strfree(*strp);
- *strp = news;
- return (0);
}
static void
@@ -38,10 +42,7 @@ http_headers_reset(nni_list *hdrs)
{
http_header *h;
while ((h = nni_list_first(hdrs)) != NULL) {
- nni_list_remove(hdrs, h);
- nni_strfree(h->name);
- nni_strfree(h->value);
- NNI_FREE_STRUCT(h);
+ nni_http_free_header(h);
}
}
@@ -51,57 +52,35 @@ http_entity_reset(nni_http_entity *entity)
if (entity->own && entity->size) {
nni_free(entity->data, entity->size);
}
- entity->data = NULL;
- entity->size = 0;
- entity->own = false;
+ http_headers_reset(&entity->hdrs);
+ nni_free(entity->buf, entity->bufsz);
+ entity->data = NULL;
+ entity->size = 0;
+ entity->own = false;
+ entity->parsed = false;
+ entity->buf = NULL;
+ entity->bufsz = 0;
}
void
nni_http_req_reset(nni_http_req *req)
{
- http_headers_reset(&req->hdrs);
http_entity_reset(&req->data);
- nni_strfree(req->uri);
+ if (req->uri != req->ubuf) {
+ nni_strfree(req->uri);
+ }
req->uri = NULL;
- nni_free(req->buf, req->bufsz);
- nni_http_req_set_method(req, NULL);
- nni_http_req_set_version(req, NNG_HTTP_VERSION_1_1);
- req->bufsz = 0;
- req->buf = NULL;
- req->parsed = false;
+ (void) snprintf(req->meth, sizeof(req->meth), "GET");
}
void
nni_http_res_reset(nni_http_res *res)
{
- http_headers_reset(&res->hdrs);
http_entity_reset(&res->data);
nni_strfree(res->rsn);
- res->vers = NNG_HTTP_VERSION_1_1;
- res->rsn = NULL;
- res->code = 0;
- res->parsed = false;
- nni_free(res->buf, res->bufsz);
- res->buf = NULL;
- res->bufsz = 0;
-}
-
-void
-nni_http_req_free(nni_http_req *req)
-{
- if (req != NULL) {
- nni_http_req_reset(req);
- NNI_FREE_STRUCT(req);
- }
-}
-
-void
-nni_http_res_free(nni_http_res *res)
-{
- if (res != NULL) {
- nni_http_res_reset(res);
- NNI_FREE_STRUCT(res);
- }
+ res->vers = NNG_HTTP_VERSION_1_1;
+ res->rsn = NULL;
+ res->code = 0;
}
static int
@@ -110,10 +89,7 @@ http_del_header(nni_list *hdrs, const char *key)
http_header *h;
NNI_LIST_FOREACH (hdrs, h) {
if (nni_strcasecmp(key, h->name) == 0) {
- nni_list_remove(hdrs, h);
- nni_strfree(h->name);
- nni_free(h->value, strlen(h->value) + 1);
- NNI_FREE_STRUCT(h);
+ nni_http_free_header(h);
return (0);
}
}
@@ -123,127 +99,21 @@ http_del_header(nni_list *hdrs, const char *key)
int
nni_http_req_del_header(nni_http_req *req, const char *key)
{
- return (http_del_header(&req->hdrs, key));
-}
-
-int
-nni_http_res_del_header(nni_http_res *res, const char *key)
-{
- return (http_del_header(&res->hdrs, key));
-}
-
-static int
-http_set_header(nni_list *hdrs, const char *key, const char *val)
-{
- http_header *h;
- NNI_LIST_FOREACH (hdrs, h) {
- if (nni_strcasecmp(key, h->name) == 0) {
- char *news;
- if ((news = nni_strdup(val)) == NULL) {
- return (NNG_ENOMEM);
- }
- nni_strfree(h->value);
- h->value = news;
- return (0);
- }
- }
-
- if ((h = NNI_ALLOC_STRUCT(h)) == NULL) {
- return (NNG_ENOMEM);
- }
- if ((h->name = nni_strdup(key)) == NULL) {
- NNI_FREE_STRUCT(h);
- return (NNG_ENOMEM);
- }
- if ((h->value = nni_strdup(val)) == NULL) {
- nni_strfree(h->name);
- NNI_FREE_STRUCT(h);
- return (NNG_ENOMEM);
- }
- nni_list_append(hdrs, h);
- return (0);
-}
-
-int
-nni_http_req_set_header(nni_http_req *req, const char *key, const char *val)
-{
- return (http_set_header(&req->hdrs, key, val));
-}
-
-int
-nni_http_res_set_header(nni_http_res *res, const char *key, const char *val)
-{
- return (http_set_header(&res->hdrs, key, val));
-}
-
-static int
-http_add_header(nni_list *hdrs, const char *key, const char *val)
-{
- http_header *h;
- NNI_LIST_FOREACH (hdrs, h) {
- if (nni_strcasecmp(key, h->name) == 0) {
- char *news;
- int rv;
- rv = nni_asprintf(&news, "%s, %s", h->value, val);
- if (rv != 0) {
- return (rv);
- }
- nni_strfree(h->value);
- h->value = news;
- return (0);
- }
- }
-
- if ((h = NNI_ALLOC_STRUCT(h)) == NULL) {
- return (NNG_ENOMEM);
- }
- if ((h->name = nni_strdup(key)) == NULL) {
- NNI_FREE_STRUCT(h);
- return (NNG_ENOMEM);
+ int rv = NNG_ENOENT;
+ while (http_del_header(&req->data.hdrs, key) == 0) {
+ rv = 0;
}
- if ((h->value = nni_strdup(val)) == NULL) {
- nni_strfree(h->name);
- NNI_FREE_STRUCT(h);
- return (NNG_ENOMEM);
- }
- nni_list_append(hdrs, h);
- return (0);
-}
-
-int
-nni_http_req_add_header(nni_http_req *req, const char *key, const char *val)
-{
- return (http_add_header(&req->hdrs, key, val));
+ return (rv);
}
int
-nni_http_res_add_header(nni_http_res *res, const char *key, const char *val)
-{
- return (http_add_header(&res->hdrs, key, val));
-}
-
-static const char *
-http_get_header(const nni_list *hdrs, const char *key)
+nni_http_res_del_header(nni_http_res *res, const char *key)
{
- http_header *h;
- NNI_LIST_FOREACH (hdrs, h) {
- if (nni_strcasecmp(h->name, key) == 0) {
- return (h->value);
- }
+ int rv = NNG_ENOENT;
+ while (http_del_header(&res->data.hdrs, key) == 0) {
+ rv = 0;
}
- return (NULL);
-}
-
-const char *
-nni_http_req_get_header(const nni_http_req *req, const char *key)
-{
- return (http_get_header(&req->hdrs, key));
-}
-
-const char *
-nni_http_res_get_header(const nni_http_res *res, const char *key)
-{
- return (http_get_header(&res->hdrs, key));
+ return (rv);
}
// http_entity_set_data sets the entity, but does not update the
@@ -273,81 +143,6 @@ http_entity_alloc_data(nni_http_entity *entity, size_t size)
return (0);
}
-static int
-http_entity_copy_data(nni_http_entity *entity, const void *data, size_t size)
-{
- int rv;
- if ((rv = http_entity_alloc_data(entity, size)) == 0) {
- memcpy(entity->data, data, size);
- }
- return (rv);
-}
-
-static int
-http_set_content_length(nni_http_entity *entity, nni_list *hdrs)
-{
- char buf[16];
- (void) snprintf(buf, sizeof(buf), "%u", (unsigned) entity->size);
- return (http_set_header(hdrs, "Content-Length", buf));
-}
-
-static void
-http_entity_get_data(nni_http_entity *entity, void **datap, size_t *sizep)
-{
- *datap = entity->data;
- *sizep = entity->size;
-}
-
-void
-nni_http_req_get_data(nni_http_req *req, void **datap, size_t *sizep)
-{
- http_entity_get_data(&req->data, datap, sizep);
-}
-
-void
-nni_http_res_get_data(nni_http_res *res, void **datap, size_t *sizep)
-{
- http_entity_get_data(&res->data, datap, sizep);
-}
-
-int
-nni_http_req_set_data(nni_http_req *req, const void *data, size_t size)
-{
- int rv;
-
- http_entity_set_data(&req->data, data, size);
- if ((rv = http_set_content_length(&req->data, &req->hdrs)) != 0) {
- http_entity_set_data(&req->data, NULL, 0);
- }
- return (rv);
-}
-
-int
-nni_http_res_set_data(nni_http_res *res, const void *data, size_t size)
-{
- int rv;
-
- http_entity_set_data(&res->data, data, size);
- if ((rv = http_set_content_length(&res->data, &res->hdrs)) != 0) {
- http_entity_set_data(&res->data, NULL, 0);
- }
- res->iserr = false;
- return (rv);
-}
-
-int
-nni_http_req_copy_data(nni_http_req *req, const void *data, size_t size)
-{
- int rv;
-
- if (((rv = http_entity_copy_data(&req->data, data, size)) != 0) ||
- ((rv = http_set_content_length(&req->data, &req->hdrs)) != 0)) {
- http_entity_set_data(&req->data, NULL, 0);
- return (rv);
- }
- return (0);
-}
-
int
nni_http_req_alloc_data(nni_http_req *req, size_t size)
{
@@ -359,20 +154,6 @@ nni_http_req_alloc_data(nni_http_req *req, size_t size)
return (0);
}
-int
-nni_http_res_copy_data(nni_http_res *res, const void *data, size_t size)
-{
- int rv;
-
- if (((rv = http_entity_copy_data(&res->data, data, size)) != 0) ||
- ((rv = http_set_content_length(&res->data, &res->hdrs)) != 0)) {
- http_entity_set_data(&res->data, NULL, 0);
- return (rv);
- }
- res->iserr = false;
- return (0);
-}
-
// nni_http_res_alloc_data allocates the data region, but does not update any
// headers. The intended use is for client implementations that want to
// allocate a buffer to receive the entity into.
@@ -394,7 +175,7 @@ nni_http_res_is_error(nni_http_res *res)
}
static int
-http_parse_header(nni_list *hdrs, void *line)
+http_parse_header(nng_http *conn, void *line)
{
char *key = line;
char *val;
@@ -418,7 +199,7 @@ http_parse_header(nni_list *hdrs, void *line)
end--;
}
- return (http_add_header(hdrs, key, val));
+ return (nni_http_add_header(conn, key, val));
}
// http_sprintf_headers makes headers for an HTTP request or an HTTP response
@@ -494,258 +275,77 @@ http_req_prepare(nni_http_req *req)
if (req->uri == NULL) {
return (NNG_EINVAL);
}
- rv = http_asprintf(&req->buf, &req->bufsz, &req->hdrs, "%s %s %s\r\n",
- req->meth, req->uri, req->vers);
+ rv = http_asprintf(&req->data.buf, &req->data.bufsz, &req->data.hdrs,
+ "%s %s %s\r\n", req->meth, req->uri, req->vers);
return (rv);
}
static int
-http_res_prepare(nni_http_res *res)
+http_res_prepare(nng_http *conn)
{
- int rv;
+ int rv;
+ nng_http_res *res = nni_http_conn_res(conn);
+
if (res->code == 0) {
res->code = NNG_HTTP_STATUS_OK;
}
- rv = http_asprintf(&res->buf, &res->bufsz, &res->hdrs, "%s %d %s\r\n",
- res->vers, nni_http_res_get_status(res),
- nni_http_res_get_reason(res));
+ rv = http_asprintf(&res->data.buf, &res->data.bufsz, &res->data.hdrs,
+ "%s %d %s\r\n", res->vers, res->code, nni_http_get_reason(conn));
return (rv);
}
-char *
-nni_http_req_headers(nni_http_req *req)
-{
- char *s;
- size_t len;
-
- len = http_sprintf_headers(NULL, 0, &req->hdrs) + 1;
- if ((s = nni_alloc(len)) != NULL) {
- http_sprintf_headers(s, len, &req->hdrs);
- }
- return (s);
-}
-
-char *
-nni_http_res_headers(nni_http_res *res)
-{
- char *s;
- size_t len;
-
- len = http_sprintf_headers(NULL, 0, &res->hdrs) + 1;
- if ((s = nni_alloc(len)) != NULL) {
- http_sprintf_headers(s, len, &res->hdrs);
- }
- return (s);
-}
-
int
nni_http_req_get_buf(nni_http_req *req, void **data, size_t *szp)
{
int rv;
- if ((req->buf == NULL) && (rv = http_req_prepare(req)) != 0) {
+ if ((req->data.buf == NULL) && (rv = http_req_prepare(req)) != 0) {
return (rv);
}
- *data = req->buf;
- *szp = req->bufsz - 1; // exclude terminating NUL
+ *data = req->data.buf;
+ *szp = req->data.bufsz - 1; // exclude terminating NUL
return (0);
}
int
-nni_http_res_get_buf(nni_http_res *res, void **data, size_t *szp)
+nni_http_res_get_buf(nng_http *conn, void **data, size_t *szp)
{
- int rv;
+ int rv;
+ nni_http_res *res = nni_http_conn_res(conn);
- if ((res->buf == NULL) && (rv = http_res_prepare(res)) != 0) {
+ if ((res->data.buf == NULL) && (rv = http_res_prepare(conn)) != 0) {
return (rv);
}
- *data = res->buf;
- *szp = res->bufsz - 1; // exclude terminating NUL
+ *data = res->data.buf;
+ *szp = res->data.bufsz - 1; // exclude terminating NUL
return (0);
}
void
nni_http_req_init(nni_http_req *req)
{
- NNI_LIST_INIT(&req->hdrs, http_header, node);
- req->buf = NULL;
- req->bufsz = 0;
- req->data.data = NULL;
- req->data.size = 0;
- req->data.own = false;
- req->uri = NULL;
- nni_http_req_set_version(req, NNG_HTTP_VERSION_1_1);
- nni_http_req_set_method(req, "GET");
-}
-
-int
-nni_http_req_set_url(nni_http_req *req, const nng_url *url)
-{
- if (url == NULL) {
- return (0);
- }
- const char *host;
- char host_buf[264]; // 256 + 8 for port
- int rv;
- rv = nni_asprintf(&req->uri, "%s%s%s%s%s", url->u_path,
- url->u_query ? "?" : "", url->u_query ? url->u_query : "",
- url->u_fragment ? "#" : "",
- url->u_fragment ? url->u_fragment : "");
- if (rv != 0) {
- return (NNG_ENOMEM);
- }
-
- // Add a Host: header since we know that from the URL. Also,
- // only include the :port portion if it isn't the default port.
- if (nni_url_default_port(url->u_scheme) == url->u_port) {
- host = url->u_hostname;
- } else {
- if (strchr(url->u_hostname, ':')) {
- snprintf(host_buf, sizeof(host_buf), "[%s]:%u",
- url->u_hostname, url->u_port);
- } else {
- snprintf(host_buf, sizeof(host_buf), "%s:%u",
- url->u_hostname, url->u_port);
- }
- host = host_buf;
- }
- if ((rv = nni_http_req_set_header(req, "Host", host)) != 0) {
- return (rv);
- }
- return (0);
-}
-
-int
-nni_http_req_alloc(nni_http_req **reqp, const nng_url *url)
-{
- nni_http_req *req;
- if ((req = NNI_ALLOC_STRUCT(req)) == NULL) {
- return (NNG_ENOMEM);
- }
- nni_http_req_init(req);
- if (url != NULL) {
- int rv;
- if ((rv = nni_http_req_set_url(req, url)) != 0) {
- nni_http_req_free(req);
- return (rv);
- }
- }
- *reqp = req;
- return (0);
+ NNI_LIST_INIT(&req->data.hdrs, http_header, node);
+ req->data.buf = NULL;
+ req->data.bufsz = 0;
+ req->data.data = NULL;
+ req->data.size = 0;
+ req->data.own = false;
+ req->uri = NULL;
+ (void) snprintf(req->meth, sizeof(req->meth), "GET");
}
void
nni_http_res_init(nni_http_res *res)
{
- NNI_LIST_INIT(&res->hdrs, http_header, node);
- res->buf = NULL;
- res->bufsz = 0;
- res->data.data = NULL;
- res->data.size = 0;
- res->data.own = false;
- res->vers = NNG_HTTP_VERSION_1_1;
- res->rsn = NULL;
- res->code = 0;
-}
-
-int
-nni_http_res_alloc(nni_http_res **resp)
-{
- nni_http_res *res;
- if ((res = NNI_ALLOC_STRUCT(res)) == NULL) {
- return (NNG_ENOMEM);
- }
- nni_http_res_init(res);
- *resp = res;
- return (0);
-}
-
-const char *
-nni_http_req_get_method(const nni_http_req *req)
-{
- return (req->meth);
-}
-
-const char *
-nni_http_req_get_uri(const nni_http_req *req)
-{
- return (req->uri != NULL ? req->uri : "");
-}
-
-const char *
-nni_http_req_get_version(const nni_http_req *req)
-{
- return (req->vers);
-}
-
-const char *
-nni_http_res_get_version(const nni_http_res *res)
-{
- 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)
-{
- return (http_set_version(&req->vers, vers));
-}
-
-int
-nni_http_res_set_version(nni_http_res *res, const char *vers)
-{
- return (http_set_version(&res->vers, vers));
-}
-
-int
-nni_http_req_set_uri(nni_http_req *req, const char *uri)
-{
- return (http_set_string(&req->uri, uri));
-}
-
-void
-nni_http_req_set_method(nni_http_req *req, const char *meth)
-{
- if (meth == NULL) {
- meth = "GET";
- }
- // this may truncate the method, but nobody should be sending
- // methods so long.
- (void) snprintf(req->meth, sizeof(req->meth), "%s", meth);
-}
-
-void
-nni_http_res_set_status(nni_http_res *res, uint16_t status)
-{
- res->code = status;
-}
-
-uint16_t
-nni_http_res_get_status(const nni_http_res *res)
-{
- return (res->code);
+ NNI_LIST_INIT(&res->data.hdrs, http_header, node);
+ res->data.buf = NULL;
+ res->data.bufsz = 0;
+ res->data.data = NULL;
+ res->data.size = 0;
+ res->data.own = false;
+ res->vers = NNG_HTTP_VERSION_1_1;
+ res->rsn = NULL;
+ res->code = 0;
}
static int
@@ -782,7 +382,7 @@ http_scan_line(void *vbuf, size_t n, size_t *lenp)
}
static int
-http_req_parse_line(nni_http_req *req, void *line)
+http_req_parse_line(nng_http *conn, void *line)
{
int rv;
char *method;
@@ -802,17 +402,16 @@ http_req_parse_line(nni_http_req *req, void *line)
*version = '\0';
version++;
- nni_http_req_set_method(req, method);
- if (((rv = nni_http_req_set_uri(req, uri)) != 0) ||
- ((rv = nni_http_req_set_version(req, version)) != 0)) {
+ nni_http_set_method(conn, method);
+ if (((rv = nni_http_set_uri(conn, uri, NULL)) != 0) ||
+ ((rv = nni_http_set_version(conn, version)) != 0)) {
return (rv);
}
- req->parsed = true;
return (0);
}
static int
-http_res_parse_line(nni_http_res *res, uint8_t *line)
+http_res_parse_line(nng_http *conn, uint8_t *line)
{
int rv;
char *reason;
@@ -838,13 +437,13 @@ http_res_parse_line(nni_http_res *res, uint8_t *line)
return (NNG_EPROTO);
}
- nni_http_res_set_status(res, (uint16_t) status);
+ if ((rv = nni_http_set_status(conn, (uint16_t) status, reason)) != 0) {
+ return (rv);
+ }
- if (((rv = nni_http_res_set_version(res, version)) != 0) ||
- ((rv = nni_http_res_set_reason(res, reason)) != 0)) {
+ if ((rv = nni_http_set_version(conn, version)) != 0) {
return (rv);
}
- res->parsed = true;
return (0);
}
@@ -855,12 +454,13 @@ http_res_parse_line(nni_http_res *res, uint8_t *line)
// be updated even in the face of errors (esp. NNG_EAGAIN, which is
// not an error so much as a request for more data.)
int
-nni_http_req_parse(nni_http_req *req, void *buf, size_t n, size_t *lenp)
+nni_http_req_parse(nng_http *conn, void *buf, size_t n, size_t *lenp)
{
- size_t len = 0;
- size_t cnt;
- int rv = 0;
+ size_t len = 0;
+ size_t cnt;
+ int rv = 0;
+ nni_http_req *req = nni_http_conn_req(conn);
for (;;) {
uint8_t *line;
@@ -877,10 +477,10 @@ nni_http_req_parse(nni_http_req *req, void *buf, size_t n, size_t *lenp)
break;
}
- if (req->parsed) {
- rv = http_parse_header(&req->hdrs, line);
- } else {
- rv = http_req_parse_line(req, line);
+ if (req->data.parsed) {
+ rv = http_parse_header(conn, line);
+ } else if ((rv = http_req_parse_line(conn, line)) == 0) {
+ req->data.parsed = true;
}
if (rv != 0) {
@@ -888,17 +488,21 @@ nni_http_req_parse(nni_http_req *req, void *buf, size_t n, size_t *lenp)
}
}
+ if (rv == 0) {
+ req->data.parsed = false;
+ }
*lenp = len;
return (rv);
}
int
-nni_http_res_parse(nni_http_res *res, void *buf, size_t n, size_t *lenp)
+nni_http_res_parse(nng_http *conn, void *buf, size_t n, size_t *lenp)
{
- size_t len = 0;
- size_t cnt;
- int rv = 0;
+ size_t len = 0;
+ size_t cnt;
+ int rv = 0;
+ nng_http_res *res = nni_http_conn_res(conn);
for (;;) {
uint8_t *line;
if ((rv = http_scan_line(buf, n, &cnt)) != 0) {
@@ -914,10 +518,10 @@ nni_http_res_parse(nni_http_res *res, void *buf, size_t n, size_t *lenp)
break;
}
- if (res->parsed) {
- rv = http_parse_header(&res->hdrs, line);
- } else {
- rv = http_res_parse_line(res, line);
+ if (res->data.parsed) {
+ rv = http_parse_header(conn, line);
+ } else if ((rv = http_res_parse_line(conn, line)) == 0) {
+ res->data.parsed = true;
}
if (rv != 0) {
@@ -925,171 +529,9 @@ nni_http_res_parse(nni_http_res *res, void *buf, size_t n, size_t *lenp)
}
}
+ if (rv == 0) {
+ res->data.parsed = false;
+ }
*lenp = len;
return (rv);
}
-
-static struct {
- uint16_t code;
- const char *mesg;
-} http_status[] = {
- // 200, listed first because most likely
- { NNG_HTTP_STATUS_OK, "OK" },
-
- // 100 series -- informational
- { NNG_HTTP_STATUS_CONTINUE, "Continue" },
- { NNG_HTTP_STATUS_SWITCHING, "Switching Protocols" },
- { NNG_HTTP_STATUS_PROCESSING, "Processing" },
-
- // 200 series -- successful
- { NNG_HTTP_STATUS_CREATED, "Created" },
- { NNG_HTTP_STATUS_ACCEPTED, "Accepted" },
- { NNG_HTTP_STATUS_NOT_AUTHORITATIVE, "Not Authoritative" },
- { NNG_HTTP_STATUS_NO_CONTENT, "No Content" },
- { NNG_HTTP_STATUS_RESET_CONTENT, "Reset Content" },
- { NNG_HTTP_STATUS_PARTIAL_CONTENT, "Partial Content" },
-
- // 300 series -- redirection
- { NNG_HTTP_STATUS_MULTIPLE_CHOICES, "Multiple Choices" },
- { NNG_HTTP_STATUS_STATUS_MOVED_PERMANENTLY, "Moved Permanently" },
- { NNG_HTTP_STATUS_FOUND, "Found" },
- { NNG_HTTP_STATUS_SEE_OTHER, "See Other" },
- { NNG_HTTP_STATUS_NOT_MODIFIED, "Not Modified" },
- { NNG_HTTP_STATUS_USE_PROXY, "Use Proxy" },
- { NNG_HTTP_STATUS_TEMPORARY_REDIRECT, "Temporary Redirect" },
-
- // 400 series -- client errors
- { NNG_HTTP_STATUS_BAD_REQUEST, "Bad Request" },
- { NNG_HTTP_STATUS_UNAUTHORIZED, "Unauthorized" },
- { NNG_HTTP_STATUS_PAYMENT_REQUIRED, "Payment Required" },
- { NNG_HTTP_STATUS_FORBIDDEN, "Forbidden" },
- { NNG_HTTP_STATUS_NOT_FOUND, "Not Found" },
- { NNG_HTTP_STATUS_METHOD_NOT_ALLOWED, "Method Not Allowed" },
- { NNG_HTTP_STATUS_NOT_ACCEPTABLE, "Not Acceptable" },
- { NNG_HTTP_STATUS_PROXY_AUTH_REQUIRED,
- "Proxy Authentication Required" },
- { NNG_HTTP_STATUS_REQUEST_TIMEOUT, "Request Timeout" },
- { NNG_HTTP_STATUS_CONFLICT, "Conflict" },
- { NNG_HTTP_STATUS_GONE, "Gone" },
- { NNG_HTTP_STATUS_LENGTH_REQUIRED, "Length Required" },
- { NNG_HTTP_STATUS_PRECONDITION_FAILED, "Precondition Failed" },
- { NNG_HTTP_STATUS_ENTITY_TOO_LONG, "Request Entity Too Long" },
- { NNG_HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE, "Unsupported Media Type" },
- { NNG_HTTP_STATUS_RANGE_NOT_SATISFIABLE,
- "Requested Range Not Satisfiable" },
- { NNG_HTTP_STATUS_EXPECTATION_FAILED, "Expectation Failed" },
- { NNG_HTTP_STATUS_TEAPOT, "I Am A Teapot" },
- { NNG_HTTP_STATUS_LOCKED, "Locked" },
- { NNG_HTTP_STATUS_FAILED_DEPENDENCY, "Failed Dependency" },
- { NNG_HTTP_STATUS_UPGRADE_REQUIRED, "Upgrade Required" },
- { NNG_HTTP_STATUS_PRECONDITION_REQUIRED, "Precondition Required" },
- { NNG_HTTP_STATUS_TOO_MANY_REQUESTS, "Too Many Requests" },
- { NNG_HTTP_STATUS_HEADERS_TOO_LARGE, "Headers Too Large" },
- { NNG_HTTP_STATUS_UNAVAIL_LEGAL_REASONS,
- "Unavailable For Legal Reasons" },
-
- // 500 series -- server errors
- { NNG_HTTP_STATUS_INTERNAL_SERVER_ERROR, "Internal Server Error" },
- { NNG_HTTP_STATUS_NOT_IMPLEMENTED, "Not Implemented" },
- { NNG_HTTP_STATUS_BAD_REQUEST, "Bad Gateway" },
- { NNG_HTTP_STATUS_SERVICE_UNAVAILABLE, "Service Unavailable" },
- { NNG_HTTP_STATUS_GATEWAY_TIMEOUT, "Gateway Timeout" },
- { NNG_HTTP_STATUS_HTTP_VERSION_NOT_SUPP,
- "HTTP Version Not Supported" },
- { NNG_HTTP_STATUS_VARIANT_ALSO_NEGOTIATES, "Variant Also Negotiates" },
- { NNG_HTTP_STATUS_INSUFFICIENT_STORAGE, "Insufficient Storage" },
- { NNG_HTTP_STATUS_LOOP_DETECTED, "Loop Detected" },
- { NNG_HTTP_STATUS_NOT_EXTENDED, "Not Extended" },
- { NNG_HTTP_STATUS_NETWORK_AUTH_REQUIRED,
- "Network Authentication Required" },
-
- // Terminator
- { 0, NULL },
-};
-
-const char *
-nni_http_reason(uint16_t code)
-{
- for (int i = 0; http_status[i].code != 0; i++) {
- if (http_status[i].code == code) {
- return (http_status[i].mesg);
- }
- }
- return ("Unknown HTTP Status");
-}
-
-const char *
-nni_http_res_get_reason(const nni_http_res *res)
-{
- return (res->rsn ? res->rsn : nni_http_reason(res->code));
-}
-
-int
-nni_http_res_set_reason(nni_http_res *res, const char *reason)
-{
- if ((reason != NULL) &&
- (strcmp(reason, nni_http_reason(res->code)) == 0)) {
- reason = NULL;
- }
- return (http_set_string(&res->rsn, reason));
-}
-
-int
-nni_http_alloc_html_error(char **html, uint16_t code, const char *details)
-{
- const char *rsn = nni_http_reason(code);
-
- return (nni_asprintf(html,
- "<!DOCTYPE html>\n"
- "<html><head><title>%d %s</title>\n"
- "<style>"
- "body { font-family: Arial, sans serif; text-align: center }\n"
- "h1 { font-size: 36px; }"
- "span { background-color: gray; color: white; padding: 7px; "
- "border-radius: 5px }"
- "h2 { font-size: 24px; }"
- "p { font-size: 20px; }"
- "</style></head>"
- "<body><p>&nbsp;</p>"
- "<h1><span>%d</span></h1>"
- "<h2>%s</h2>"
- "<p>%s</p>"
- "</body></html>",
- code, rsn, code, rsn, details != NULL ? details : ""));
-}
-
-int
-nni_http_res_set_error(nni_http_res *res, uint16_t err)
-{
- int rv;
- char *html = NULL;
- if (((rv = nni_http_alloc_html_error(&html, err, NULL)) != 0) ||
- ((rv = nni_http_res_set_header(
- res, "Content-Type", "text/html; charset=UTF-8")) != 0) ||
- ((rv = nni_http_res_copy_data(res, html, strlen(html))) != 0)) {
- nni_strfree(html);
- return (rv);
- }
- nni_strfree(html);
- res->code = err;
- res->iserr = true;
- return (0);
-}
-
-int
-nni_http_res_alloc_error(nni_http_res **resp, uint16_t err)
-{
- nni_http_res *res;
- int rv;
-
- if ((rv = nni_http_res_alloc(&res)) != 0) {
- return (rv);
- }
- rv = nni_http_res_set_error(res, err);
- if (rv != 0) {
- nni_http_res_free(res);
- return (rv);
- }
- *resp = res;
- return (0);
-}