Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

http: server error handling improvements and tests #2083

Merged
merged 2 commits into from
Jan 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 0 additions & 27 deletions docs/man/libnng.3.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -93,32 +93,6 @@ be the case if WebSocket support is configured as well.
In this case, it is possible to access functionality to support the creation of
HTTP (and HTTP/S if TLS support is present) servers and clients.

==== Common HTTP Functions

The following functions are used to work with HTTP requests, responses,
and connections.

|===
|xref:nng_http_conn_read_req.3http.adoc[nng_http_conn_read_req()]|read HTTP request
|xref:nng_http_conn_read_res.3http.adoc[nng_http_conn_read_res()]|read HTTP response
|xref:nng_http_conn_write_req.3http.adoc[nng_http_conn_write_req()]|write HTTP request
|xref:nng_http_conn_write_res.3http.adoc[nng_http_conn_write_res()]|write HTTP response
|xref:nng_http_req_get_data.3http.adoc[nng_http_req_get_data()]|get HTTP request body
|xref:nng_http_req_set_data.3http.adoc[nng_http_req_set_data()]|set HTTP request body
|xref:nng_http_res_copy_data.3http.adoc[nng_http_res_copy_data()]|copy HTTP response body
|xref:nng_http_res_get_data.3http.adoc[nng_http_res_get_data()]|get HTTP response body
|xref:nng_http_res_get_header.3http.adoc[nng_http_res_get_header()]|return HTTP response header
|xref:nng_http_res_set_data.3http.adoc[nng_http_res_set_data()]|set HTTP response body
|===

==== HTTP Client Functions

These functions are intended for use with HTTP client applications.

|===
|xref:nng_http_conn_transact.3http.adoc[nng_http_conn_transact()]|perform one HTTP transaction on connection
|===

==== HTTP Server Functions

These functions are intended for use with HTTP server applications.
Expand All @@ -127,7 +101,6 @@ These functions are intended for use with HTTP server applications.
|xref:nng_http_handler_alloc.3http.adoc[nng_http_handler_alloc()]|allocate HTTP server handler
|xref:nng_http_handler_collect_body.3http.adoc[nng_http_handler_collect_body()]|set HTTP handler to collect request body
|xref:nng_http_handler_free.3http.adoc[nng_http_handler_free()]|free HTTP server handler
|xref:nng_http_handler_get_data.3http.adoc[nng_http_handler_get_data()]|return extra data for HTTP handler
|xref:nng_http_handler_set_data.3http.adoc[nng_http_handler_set_data()]|set extra data for HTTP handler
|xref:nng_http_handler_set_host.3http.adoc[nng_http_handler_set_host()]|set host for HTTP handler
|xref:nng_http_handler_set_method.3http.adoc[nng_http_handler_set_method()]|set HTTP handler method
Expand Down
46 changes: 0 additions & 46 deletions docs/man/nng_http_handler_get_data.3http.adoc

This file was deleted.

3 changes: 0 additions & 3 deletions docs/man/nng_http_handler_set_data.3http.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ void nng_http_handler_set_data(nng_http_handler *handler, void *data,

The `nng_http_handler_set_data()` function is used to set an additional
_data_ for the _handler_.
The stored _data_ can be retrieved later in the handler function using
xref:nng_http_handler_get_data.3http.adoc[`nng_http_handler_get_data()`].

Additionally, when the handler is deallocated, if _dtor_ is not `NULL`,
then it will be called with _data_ as its argument.
Expand All @@ -40,6 +38,5 @@ this function is deallocate any resources associated with _data_.

[.text-left]
xref:nng_http_handler_alloc.3http.adoc[nng_http_handler_alloc(3http)],
xref:nng_http_handler_get_data.3http.adoc[nng_http_server_get_data(3http)],
xref:nng_http_server_add_handler.3http.adoc[nng_http_server_add_handler(3http)],
xref:nng.7.adoc[nng(7)]
3 changes: 0 additions & 3 deletions include/nng/http.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,9 +301,6 @@ NNG_DECL void nng_http_handler_set_tree(nng_http_handler *);
NNG_DECL void nng_http_handler_set_data(
nng_http_handler *, void *, void (*)(void *));

// nng_http_handler_get_data returns the data that was previously stored.
NNG_DECL void *nng_http_handler_get_data(nng_http_handler *);

// nng_http_server is a handle to an HTTP server instance. Servers
// only serve a single port / address at this time.

Expand Down
6 changes: 1 addition & 5 deletions src/supplemental/http/http_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -294,15 +294,11 @@ extern void nni_http_handler_set_host(nni_http_handler *, const char *);
extern void nni_http_handler_set_method(nni_http_handler *, const char *);

// nni_http_handler_set_data sets an opaque data element on the handler,
// which will be available to the callback via nni_http_handler_get_data.
// which will be available to the handler function as argument.
// The callback is an optional destructor, and will be called with the
// data as its argument, when the handler is being destroyed.
extern void nni_http_handler_set_data(nni_http_handler *, void *, nni_cb);

// nni_http_handler_get_data returns the data that was previously stored
// by nni_http_handler_set_data.
extern void *nni_http_handler_get_data(nni_http_handler *);

// nni_http_handler_get_uri returns the URI set on the handler.
extern const char *nni_http_handler_get_uri(nni_http_handler *);

Expand Down
33 changes: 19 additions & 14 deletions src/supplemental/http/http_msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,31 +213,39 @@
static int
http_req_parse_line(nng_http *conn, void *line)
{
int rv;
char *method;
char *uri;
char *version;

method = line;
if ((uri = strchr(method, ' ')) == NULL) {
return (NNG_EPROTO);
nni_http_set_status(conn, NNG_HTTP_STATUS_BAD_REQUEST, NULL);
return (0);

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

View check run for this annotation

Codecov / codecov/patch

src/supplemental/http/http_msg.c#L222-L223

Added lines #L222 - L223 were not covered by tests
}
*uri = '\0';
uri++;

if ((version = strchr(uri, ' ')) == NULL) {
return (NNG_EPROTO);
nni_http_set_status(conn, NNG_HTTP_STATUS_BAD_REQUEST, NULL);
return (0);

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

View check run for this annotation

Codecov / codecov/patch

src/supplemental/http/http_msg.c#L229-L230

Added lines #L229 - L230 were not covered by tests
}
*version = '\0';
version++;

nni_http_set_method(conn, method);
if (((rv = nni_url_canonify_uri(uri)) != 0) ||
((rv = nni_http_set_uri(conn, uri, NULL)) != 0) ||
((rv = nni_http_set_version(conn, version)) != 0)) {
return (rv);
if (nni_url_canonify_uri(uri) != 0) {
nni_http_set_status(conn, NNG_HTTP_STATUS_BAD_REQUEST, NULL);
return (0);
}
return (0);
if (nni_http_set_version(conn, version)) {
nni_http_set_status(
conn, NNG_HTTP_STATUS_HTTP_VERSION_NOT_SUPP, NULL);
return (0);

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

View check run for this annotation

Codecov / codecov/patch

src/supplemental/http/http_msg.c#L240-L242

Added lines #L240 - L242 were not covered by tests
}

nni_http_set_method(conn, method);

// this one only can fail due to ENOMEM
return (nni_http_set_uri(conn, uri, NULL));
}

static int
Expand Down Expand Up @@ -303,12 +311,9 @@

if (req->data.parsed) {
rv = http_parse_header(conn, line);
} else if ((rv = http_req_parse_line(conn, line)) == 0) {
} else {
req->data.parsed = true;
}

if (rv != 0) {
break;
rv = http_req_parse_line(conn, line);
}
}

Expand Down
11 changes: 0 additions & 11 deletions src/supplemental/http/http_public.c
Original file line number Diff line number Diff line change
Expand Up @@ -434,17 +434,6 @@ nng_http_handler_set_data(nng_http_handler *h, void *dat, void (*dtor)(void *))
#endif
}

void *
nng_http_handler_get_data(nng_http_handler *h)
{
#ifdef NNG_SUPP_HTTP
return (nni_http_handler_get_data(h));
#else
NNI_ARG_UNUSED(h);
return (NULL);
#endif
}

int
nng_http_server_hold(nng_http_server **srvp, const nng_url *url)
{
Expand Down
14 changes: 6 additions & 8 deletions src/supplemental/http/http_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,12 +163,6 @@ nni_http_handler_set_data(nni_http_handler *h, void *data, nni_cb dtor)
h->dtor = dtor;
}

void *
nni_http_handler_get_data(nni_http_handler *h)
{
return (h->data);
}

const char *
nni_http_handler_get_uri(nni_http_handler *h)
{
Expand Down Expand Up @@ -466,7 +460,11 @@ http_sconn_rxdone(void *arg)
// Validate the request -- it has to at least look like HTTP
// 1.x. We flatly refuse to deal with HTTP 0.9, and we can't
// cope with HTTP/2.
if ((val = nni_http_get_version(sc->conn)) == NULL) {
if (nng_http_get_status(sc->conn) >= NNG_HTTP_STATUS_BAD_REQUEST) {
http_sconn_error(sc, nng_http_get_status(sc->conn));
return;
}
if ((val = nng_http_get_version(sc->conn)) == NULL) {
sc->close = true;
http_sconn_error(sc, NNG_HTTP_STATUS_BAD_REQUEST);
return;
Expand All @@ -485,7 +483,7 @@ http_sconn_rxdone(void *arg)
}

// NB: The URI will already have been canonified by the REQ parser
uri = nni_http_get_uri(sc->conn);
uri = nng_http_get_uri(sc->conn);
if (uri[0] != '/') {
// We do not support authority form or asterisk form at present
sc->close = true;
Expand Down
Loading
Loading