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 conn req res inline #2074

Merged
merged 3 commits into from
Jan 6, 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
10 changes: 5 additions & 5 deletions docs/man/nng_http_conn_read_req.3http.adoc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
= nng_http_conn_read_req(3http)
//
// Copyright 2018 Staysail Systems, Inc. <[email protected]>
// Copyright 2025 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,15 +20,15 @@ nng_http_conn_read_req - read HTTP request
#include <nng/nng.h>
#include <nng/supplemental/http/http.h>

void nng_http_conn_read_req(nng_http_conn *conn, nng_http_req *req,
nng_aio *aio);
void nng_http_conn_read_req(nng_http_conn *conn, nng_aio *aio);
----

== DESCRIPTION

The `nng_http_conn_read_req()` function starts an asynchronous read from the
HTTP connection _conn_, reading an HTTP request into the _req_, including all
of the related headers.
HTTP connection _conn_, reading an HTTP request into the request object
associated with _conn_, including all of the related headers.
(The request object can be obtained via `nng_http_conn_req()`.

NOTE: Any HTTP entity/body data associated with the request is *not* read
automatically.
Expand Down
7 changes: 3 additions & 4 deletions docs/man/nng_http_conn_write_res.3http.adoc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
= nng_http_conn_write_res(3http)
//
// Copyright 2018 Staysail Systems, Inc. <[email protected]>
// Copyright 2025 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,14 +20,13 @@ nng_http_conn_write_res - write HTTP response
#include <nng/nng.h>
#include <nng/supplemental/http/http.h>

void nng_http_conn_write_res(nng_http_conn *conn, nng_http_res *res,
nng_aio *aio);
void nng_http_conn_write_res(nng_http_conn *conn, nng_aio *aio);
----

== DESCRIPTION

The `nng_http_conn_write_res()` function starts an asynchronous write of
the HTTP response _res_ to the connection _conn_.
the HTTP response associated with the connection _conn_.
The entire response is sent,
including headers, and if present, the response body data.
(The response body can be set with
Expand Down
29 changes: 13 additions & 16 deletions docs/man/nng_http_handler_alloc.3http.adoc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
= nng_http_handler_alloc(3http)
//
// Copyright 2018 Staysail Systems, Inc. <[email protected]>
// Copyright 2025 Staysail Systems, Inc. <[email protected]>
// Copyright 2018 Capitar IT Group BV <[email protected]>
// Copyright 2020 Dirac Research <[email protected]>
//
Expand All @@ -23,8 +23,10 @@ nng_http_handler_alloc - allocate HTTP server handler

typedef struct nng_http_handler nng_http_handler;

typedef void (*nng_http_hander_func)(nng_http_conn *conn, void *arg, nng_aio *aio);

int nng_http_handler_alloc(nng_http_handler **hp, const char *path,
void (*func)(nng_aio *);
nng_http_handler_func cb);

int nng_http_handler_alloc_directory(nng_http_handler **hp, const char *path,
const char *dirname);
Expand Down Expand Up @@ -72,24 +74,19 @@ rather than just a single element.
The generic (first) form of this creates a handler that uses a user-supplied
function to process HTTP requests.
This function uses the asynchronous I/O framework.
The function takes a pointer to an xref:nng_aio.5.adoc[`nng_aio`] structure.

The _aio_ will be passed with the following input values (retrieved with
xref:nng_aio_get_input.3.adoc[`nng_aio_get_input()`]):
The function receives the connection on _conn_, and the data that it set
previously with `nng_http_handler_set_data` as the second argument. The
final argument is the _aio_, which must be "finished" to complete the operation.

0: `nng_http_req *` __request__:: The client's HTTP request.
1: `nng_http_handler *` __handler__:: Pointer to the handler object.
2: `nng_http_conn *` __conn__:: The underlying HTTP connection.
The function takes a pointer to an xref:nng_aio.5.adoc[`nng_aio`] structure.

The handler should create an `nng_http_res *` response (such as via
xref:nng_http_res_alloc.3http.adoc[`nng_http_res_alloc()`] or
xref:nng_http_res_alloc_error.3http.adoc[`nng_http_res_alloc_error()`]) and store that
in as the first output (index 0) with
xref:nng_aio_set_output.3.adoc[`nng_aio_set_output()`].
The handler should obtain `nng_http_res *` response from the
connection (`nng_http_conn_res`) and update it to reflect the final status.

Alternatively, the handler may send the HTTP response (and any associated
body data) itself using the connection.
In that case the output at index 0 of the _aio_ should be NULL.
The handler may call `nng_http_conn_write_res` to send the response, or
it may simply let the framework do so on its behalf. The server will perform
this step if the callback has not already done so.

Finally, using the xref:nng_aio_finish.3.adoc[`nng_aio_finish()`] function, the
_aio_ should be completed successfully.
Expand Down
43 changes: 23 additions & 20 deletions include/nng/supplemental/http/http.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright 2024 Staysail Systems, Inc. <[email protected]>
// Copyright 2025 Staysail Systems, Inc. <[email protected]>
// Copyright 2018 Capitar IT Group BV <[email protected]>
// Copyright 2020 Dirac Research <[email protected]>
//
Expand Down Expand Up @@ -143,6 +143,9 @@ NNG_DECL void nng_http_req_set_method(nng_http_req *, const char *);
// not support HTTP/2 at all. Null sets the default ("HTTP/1.1").
NNG_DECL int nng_http_req_set_version(nng_http_req *, const char *);

// nng_http_req_set_url is used to change the URL of a request.
NNG_DECL int nng_http_req_set_url(nng_http_req *, const nng_url *);

// nng_http_req_set_uri is used to change the URI of a request. This
// should be an "abs-uri", that is a path, plus query and fragment if
// needed. The scheme, host, and port don't belong here. The URI should
Expand Down Expand Up @@ -239,6 +242,11 @@ NNG_DECL int nng_http_res_copy_data(nng_http_res *, const void *, size_t);
// normally only used for exchanging HTTP requests and responses.
typedef struct nng_http_conn nng_http_conn;

// These methods obtain a pointer to the request or response structure
// that is embedded in the conn structure.
NNG_DECL nng_http_req *nng_http_conn_req(nng_http_conn *);
NNG_DECL nng_http_res *nng_http_conn_res(nng_http_conn *);

// nng_http_conn_close closes the underlying channel. Applications should
// not use this channel after this operation is performed.
NNG_DECL void nng_http_conn_close(nng_http_conn *);
Expand Down Expand Up @@ -267,15 +275,13 @@ NNG_DECL void nng_http_conn_write_req(
nng_http_conn *, nng_http_req *, nng_aio *);

// nng_http_conn_write_res writes the entire response. It will also write any
// data that has been attached.
NNG_DECL void nng_http_conn_write_res(
nng_http_conn *, nng_http_res *, nng_aio *);
// data that has been attached. It uses the res object in the conn.
NNG_DECL void nng_http_conn_write_res(nng_http_conn *, nng_aio *);

// nng_http_conn_read_req reads an entire request, EXCEPT for any entity
// data. The caller is responsible for processing the headers in the request
// and reading any submitted entity data itself.
NNG_DECL void nng_http_conn_read_req(
nng_http_conn *, nng_http_req *, nng_aio *);
NNG_DECL void nng_http_conn_read_req(nng_http_conn *, nng_aio *);

// nng_http_conn_read_res reads an entire response, EXCEPT for any entity
// data. The caller is responsible for processing the headers in the response
Expand All @@ -302,22 +308,20 @@ typedef struct nng_http_handler nng_http_handler;
// is registered with the server, and that a handler can only be registered
// once per server.
//
// The callback function will receive the following arguments (via
// nng_aio_get_input(): nng_http_request *, nng_http_handler *, and
// nng_http_conn *. The first is a request object, for convenience.
// The second is the handler, from which the callback can obtain any other
// data it has set. The final is the http connection, which can be used
// to hijack the session.
//
// Upon completion, the handler should store an nng_http_res * as the
// first output using nng_aio_set_output. If it does not do so, or supplies
// NULL, then it must send a response itself.
// The callback function should obtain the request (if needed), and
// the response from the connection object using nng_http_conn_req
// and nng_http_conn_res. If the connection is hijacked, then the
// response object will not be used, otherwise the server will send it on
// behalf of the client.
//
// The callback should complete with a result of 0 in most circumstances.
// If it completes with an error, then the connection is terminated, after
// possibly sending a 500 error response to the client.
// possibly sending a 500 error response to the client. The callback signals
// completion by nng_aio_finish. The second argument to this function is the
// handler data that was optionally set by nng_handler_set_data.
typedef void (*nng_http_handler_func)(nng_http_conn *, void *, nng_aio *);
NNG_DECL int nng_http_handler_alloc(
nng_http_handler **, const char *, void (*)(nng_aio *));
nng_http_handler **, const char *, nng_http_handler_func);

// nng_http_handler_free frees the handler. This actually just drops a
// reference count on the handler, as it may be in use by an existing
Expand Down Expand Up @@ -526,8 +530,7 @@ NNG_DECL void nng_http_client_connect(nng_http_client *, nng_aio *);
// single HTTP transaction). It will not automatically close the connection,
// unless some kind of significant error occurs. The caller should close
// the connection if the aio does not complete successfully.
NNG_DECL void nng_http_conn_transact(
nng_http_conn *, nng_http_req *, nng_http_res *, nng_aio *);
NNG_DECL void nng_http_conn_transact(nng_http_conn *, nng_aio *);

// nng_http_client_transact is used to execute a single transaction to a
// server. The connection is opened, and will be closed when the transaction is
Expand Down
11 changes: 0 additions & 11 deletions src/platform/posix/posix_tcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,6 @@ struct nni_tcp_conn {
nni_reap_node reap;
};

struct nni_tcp_dialer {
nni_list connq; // pending connections
bool closed;
bool nodelay;
bool keepalive;
struct sockaddr_storage src;
size_t srclen;
nni_mtx mtx;
nni_refcnt ref;
};

extern int nni_posix_tcp_alloc(nni_tcp_conn **, nni_tcp_dialer *, int);
extern void nni_posix_tcp_start(nni_tcp_conn *, int, int);
extern void nni_posix_tcp_dialer_rele(nni_tcp_dialer *);
Expand Down
11 changes: 11 additions & 0 deletions src/platform/posix/posix_tcpdial.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,17 @@
#endif
#endif

struct nni_tcp_dialer {
nni_list connq; // pending connections
bool closed;
bool nodelay;
bool keepalive;
struct sockaddr_storage src;
size_t srclen;
nni_mtx mtx;
nni_refcnt ref;
};

static void tcp_dialer_fini(void *arg);

// Dialer stuff.
Expand Down
30 changes: 16 additions & 14 deletions src/supplemental/http/http_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,14 @@ typedef struct nng_http_chunks nni_http_chunks;

extern const char *nni_http_reason(uint16_t);

extern int nni_http_req_init(nni_http_req **);
extern void nni_http_req_init(nni_http_req *);
extern void nni_http_req_reset(nni_http_req *);
extern int nni_http_req_get_buf(nni_http_req *, void **, size_t *);
extern int nni_http_req_parse(nni_http_req *, void *, size_t, size_t *);
extern char *nni_http_req_headers(nni_http_req *);
extern void nni_http_req_get_data(nni_http_req *, void **, size_t *);

extern void nni_http_res_init(nni_http_res *);
extern void nni_http_res_reset(nni_http_res *);
extern int nni_http_res_get_buf(nni_http_res *, void **, size_t *);
extern int nni_http_res_parse(nni_http_res *, void *, size_t, size_t *);
Expand Down Expand Up @@ -74,6 +75,9 @@ extern int nni_http_chunks_parse(nni_http_chunks *, void *, size_t, size_t *);
extern void nni_http_read_chunks(
nni_http_conn *, nni_http_chunks *, nni_aio *);

extern nni_http_req *nni_http_conn_req(nni_http_conn *);
extern nni_http_res *nni_http_conn_res(nni_http_conn *);

// Private to the server. (Used to support session hijacking.)
extern void nni_http_conn_set_ctx(nni_http_conn *, void *);
extern void *nni_http_conn_get_ctx(nni_http_conn *);
Expand Down Expand Up @@ -110,12 +114,13 @@ extern int nni_http_conn_getopt(
extern int nni_http_req_alloc(nni_http_req **, const nng_url *);
extern int nni_http_res_alloc(nni_http_res **);
extern int nni_http_res_alloc_error(nni_http_res **, uint16_t);
extern int nni_http_res_set_error(nni_http_res *, uint16_t);
extern void nni_http_req_free(nni_http_req *);
extern void nni_http_res_free(nni_http_res *);
extern void nni_http_write_req(nni_http_conn *, nni_http_req *, nni_aio *);
extern void nni_http_write_res(nni_http_conn *, nni_http_res *, nni_aio *);
extern void nni_http_read_req(nni_http_conn *, nni_http_req *, nni_aio *);
extern void nni_http_read_res(nni_http_conn *, nni_http_res *, nni_aio *);
extern void nni_http_read_req(nni_http_conn *, nni_aio *);
extern void nni_http_write_res(nni_http_conn *, nni_aio *);

extern const char *nni_http_req_get_header(const nni_http_req *, const char *);
extern const char *nni_http_res_get_header(const nni_http_res *, const char *);
Expand All @@ -137,6 +142,7 @@ extern const char *nni_http_req_get_uri(const nni_http_req *);
extern void nni_http_req_set_method(nni_http_req *, const char *);
extern int nni_http_req_set_version(nni_http_req *, const char *);
extern int nni_http_req_set_uri(nni_http_req *, const char *);
extern int nni_http_req_set_url(nni_http_req *, const nng_url *);
extern uint16_t nni_http_res_get_status(const nni_http_res *);
extern void nni_http_res_set_status(nni_http_res *, uint16_t);
extern const char *nni_http_res_get_version(const nni_http_res *);
Expand Down Expand Up @@ -253,15 +259,8 @@ extern int nni_http_hijack(nni_http_conn *);
// Note that methods which modify a handler cannot be called while the handler
// is registered with the server, and that a handler can only be registered
// once per server.
//
// The callback function will receive the following arguments (via
// nng_aio_get_input(): nni_http_request *, nni_http_handler *, and
// nni_http_conn_t *. The first is a request object, for convenience.
// The second is the handler, from which the callback can obtain any other
// data it has set. The final is the http context, from which its possible
// to hijack the session.
extern int nni_http_handler_init(
nni_http_handler **, const char *, void (*)(nni_aio *));
nni_http_handler **, const char *, nng_http_handler_func);

// nni_http_handler_init_file creates a handler with a function to serve
// up a file named in the last argument.
Expand Down Expand Up @@ -375,9 +374,9 @@ extern void nni_http_client_connect(nni_http_client *, nni_aio *);
// unless some kind of significant error occurs. The caller should dispose
// of the connection if the aio does not complete successfully.
// Note that this will fail with NNG_ENOTSUP if the server attempts to reply
// with a chunked transfer encoding.
extern void nni_http_transact_conn(
nni_http_conn *, nni_http_req *, nni_http_res *, nni_aio *);
// with a chunked transfer encoding. The request and response used are the
// ones associated with the connection.
extern void nni_http_transact_conn(nni_http_conn *, nni_aio *);

// nni_http_transact is used to execute a single transaction to a server.
// The connection is opened, and will be closed when the transaction is
Expand All @@ -390,4 +389,7 @@ extern void nni_http_transact(
// upper layer scheme.
extern const char *nni_http_stream_scheme(const char *);

// Private method used for the server.
extern bool nni_http_conn_res_sent(nni_http_conn *conn);

#endif // NNG_SUPPLEMENTAL_HTTP_HTTP_API_H
11 changes: 6 additions & 5 deletions src/supplemental/http/http_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,8 +361,7 @@ http_txn_cancel(nni_aio *aio, void *arg, int rv)
// for Chunked Transfer Encoding is missing. Note that cancelling the aio
// is generally fatal to the connection.
void
nni_http_transact_conn(
nni_http_conn *conn, nni_http_req *req, nni_http_res *res, nni_aio *aio)
nni_http_transact_conn(nni_http_conn *conn, nni_aio *aio)
{
http_txn *txn;
int rv;
Expand All @@ -380,10 +379,12 @@ nni_http_transact_conn(
nni_aio_list_init(&txn->aios);
txn->client = NULL;
txn->conn = conn;
txn->req = req;
txn->res = res;
txn->req = nni_http_conn_req(conn);
txn->res = nni_http_conn_res(conn);
txn->state = HTTP_SENDING;

nni_http_res_reset(txn->res);

nni_mtx_lock(&http_txn_lk);
if (!nni_aio_start(aio, http_txn_cancel, txn)) {
nni_mtx_unlock(&http_txn_lk);
Expand All @@ -392,7 +393,7 @@ nni_http_transact_conn(
}
nni_http_res_reset(txn->res);
nni_list_append(&txn->aios, aio);
nni_http_write_req(conn, req, txn->aio);
nni_http_write_req(conn, txn->req, txn->aio);
nni_mtx_unlock(&http_txn_lk);
}

Expand Down
Loading
Loading