diff options
| author | Garrett D'Amore <garrett@damore.org> | 2025-01-06 15:20:09 -0800 |
|---|---|---|
| committer | Garrett D'Amore <garrett@damore.org> | 2025-01-09 23:22:56 -0800 |
| commit | 73f50e2679525e7df8734c875a3c12732565f953 (patch) | |
| tree | 23bd167dfcd95305b58a29c142b51879011f63b2 /include | |
| parent | a381af4f5ca79576a4a9b461529a0f22fcf1e088 (diff) | |
| download | nng-http-client-trans.tar.gz nng-http-client-trans.tar.bz2 nng-http-client-trans.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 'include')
| -rw-r--r-- | include/nng/http.h (renamed from include/nng/supplemental/http/http.h) | 304 | ||||
| -rw-r--r-- | include/nng/nng.h | 23 |
2 files changed, 110 insertions, 217 deletions
diff --git a/include/nng/supplemental/http/http.h b/include/nng/http.h index 344dbbe0..ec29e56e 100644 --- a/include/nng/supplemental/http/http.h +++ b/include/nng/http.h @@ -9,8 +9,8 @@ // found online at https://opensource.org/licenses/MIT. // -#ifndef NNG_SUPPLEMENTAL_HTTP_HTTP_H -#define NNG_SUPPLEMENTAL_HTTP_HTTP_H +#ifndef NNG_HTTP_H +#define NNG_HTTP_H // HTTP API. Only present if HTTP support compiled into the library. // Functions will return NNG_ENOTSUP (or NULL or 0 as appropriate) @@ -60,8 +60,8 @@ enum nng_http_status { NNG_HTTP_STATUS_GONE = 410, NNG_HTTP_STATUS_LENGTH_REQUIRED = 411, NNG_HTTP_STATUS_PRECONDITION_FAILED = 412, - NNG_HTTP_STATUS_PAYLOAD_TOO_LARGE = 413, - NNG_HTTP_STATUS_ENTITY_TOO_LONG = 414, + NNG_HTTP_STATUS_CONTENT_TOO_LARGE = 413, + NNG_HTTP_STATUS_URI_TOO_LONG = 414, NNG_HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE = 415, NNG_HTTP_STATUS_RANGE_NOT_SATISFIABLE = 416, NNG_HTTP_STATUS_EXPECTATION_FAILED = 417, @@ -69,6 +69,7 @@ enum nng_http_status { NNG_HTTP_STATUS_UNPROCESSABLE_ENTITY = 422, NNG_HTTP_STATUS_LOCKED = 423, NNG_HTTP_STATUS_FAILED_DEPENDENCY = 424, + NNG_HTTP_STATUS_TOO_EARLY = 425, NNG_HTTP_STATUS_UPGRADE_REQUIRED = 426, NNG_HTTP_STATUS_PRECONDITION_REQUIRED = 428, NNG_HTTP_STATUS_TOO_MANY_REQUESTS = 429, @@ -95,208 +96,124 @@ enum nng_http_status { // nng_http_req represents an HTTP request. typedef struct nng_http_req nng_http_req; -// nng_http_req_alloc creates a vanilla HTTP request object. The object is -// initialized with the given URL object for an HTTP/1.1 GET request by -// default. It also adds the Host: header required for HTTP/1.1. If the -// url is NULL, then the uri and Host: header are uninitialized, and will -// need to be set explicitly. -NNG_DECL int nng_http_req_alloc(nng_http_req **, const nng_url *); - -// nng_http_req_free frees an HTTP request object. -NNG_DECL void nng_http_req_free(nng_http_req *); - -// nng_http_req_get_method returns the method. -NNG_DECL const char *nng_http_req_get_method(const nng_http_req *); - -// nng_http_req_get_version returns the version, usually HTTP/1.1. -NNG_DECL const char *nng_http_req_get_version(const nng_http_req *); - -// nng_http_req_get_uri returns the "abs-uri", which is URL without -// the scheme, host, or port. -NNG_DECL const char *nng_http_req_get_uri(const nng_http_req *); - -// nng_http_req_set_header sets an HTTP header, replacing any previous value -// that might have been present. -NNG_DECL int nng_http_req_set_header( - nng_http_req *, const char *, const char *); - -// nng_http_req_add_header adds an HTTP header, without disrupting any other -// with the same name that might have been present. -NNG_DECL int nng_http_req_add_header( - nng_http_req *, const char *, const char *); - -// nng_http_req_del_header deletes all occurrences of a named header. -NNG_DECL int nng_http_req_del_header(nng_http_req *, const char *); - -// nng_http_req_get_header looks up a header with the named, returns NULL -// if not found. -NNG_DECL const char *nng_http_req_get_header( - const nng_http_req *, const char *); - -// nng_http_req_set_method is used to change the method of a request. -// The method should be an upper case HTTP method, like POST, or DELETE. -// Null sets the default ("GET"). -NNG_DECL void nng_http_req_set_method(nng_http_req *, const char *); - -// nng_http_req_set_version is used to change the version of a request. -// Normally the version is "HTTP/1.1". Note that the framework does -// 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 -// start with a leading '/' per HTTP. -NNG_DECL int nng_http_req_set_uri(nng_http_req *, const char *); - -// nng_http_req_set_data adds entity data to the request. The -// data object must persist (so only really useful for static data). -// The content-length header is updated as well, but the caller should -// probably set the content-type header. -NNG_DECL int nng_http_req_set_data(nng_http_req *, const void *, size_t); - -// nng_http_req_copy_data adds entity data to the response. A private -// copy of the data is made (will be freed with the request). -// The content-length header is updated as well, but the caller should -// probably set the content-type header. -NNG_DECL int nng_http_req_copy_data(nng_http_req *, const void *, size_t); - -// nng_http_req_get_data gets the data for the response. -NNG_DECL void nng_http_req_get_data(nng_http_req *, void **, size_t *); - // nng_http_res represents an HTTP response. typedef struct nng_http_res nng_http_res; -// nng_http_res_alloc creates a vanilla HTTP response object. The object is -// initialized for an HTTP/1.1 200 OK response by default. -NNG_DECL int nng_http_res_alloc(nng_http_res **); - -// nng_http_res_alloc_error creates an error HTTP response object. The object -// is initialized for an HTTP/1.1 response, and contains an associated -// generic HTML error page. -NNG_DECL int nng_http_res_alloc_error(nng_http_res **, uint16_t); - -// nng_http_res_free frees an HTTP response object. -NNG_DECL void nng_http_res_free(nng_http_res *); - -// nng_http_res_get_status returns the HTTP status code from the server. -NNG_DECL uint16_t nng_http_res_get_status(const nng_http_res *); +// An nng_http represents an underlying "connection". It may be +// a TCP channel, or a TLS channel, but the main thing is that this is +// normally only used for exchanging HTTP requests and responses. +typedef struct nng_http_conn nng_http; -// nng_http_res_set_status sets the HTTP status code. -NNG_DECL void nng_http_res_set_status(nng_http_res *, uint16_t); +// These methods obtain a pointer to the request or response structure +// that is embedded in the conn structure. +NNG_DECL nng_http_res *nng_http_conn_res(nng_http *); -// nng_http_res_get_reason returns the human readable status message -// that the server responds (or responded) with. -NNG_DECL const char *nng_http_res_get_reason(const nng_http_res *); +// nng_http_close closes the underlying channel. Applications should +// not use this channel after this operation is performed. +NNG_DECL void nng_http_close(nng_http *); -// nng_http_res_set_reason sets the human readable status message. -// NULL means that a default reason is used based on the status code. -NNG_DECL int nng_http_res_set_reason(nng_http_res *, const char *); +// nng_http_read attempts to read data from the connection. This +// completes as soon as at least one byte is read; it does not wait +// for the entire aio to be filled. +NNG_DECL void nng_http_read(nng_http *, nng_aio *); -// nng_http_res_set_header sets an HTTP header, replacing any previous value -// that might have been present. -NNG_DECL int nng_http_res_set_header( - nng_http_res *, const char *, const char *); +// nng_http_read_all is like nng_http_read, but it does not +// finish until either all the requested data is read, or an error occurs. +NNG_DECL void nng_http_read_all(nng_http *, nng_aio *); -// nng_http_res_add_header adds an HTTP header, without disrupting any other -// with the same name that might have been present. -NNG_DECL int nng_http_res_add_header( - nng_http_res *, const char *, const char *); +// nng_http_write attempts to write data, but it can write less +// than the amount requested. (It completes as soon as at least one +// byte is written.) +NNG_DECL void nng_http_write(nng_http *, nng_aio *); -// nng_http_res_del_header deletes all occurrences of a named header. -NNG_DECL int nng_http_res_del_header(nng_http_res *, const char *); +// nng_http_write_all is like nng_http_write, but it does not +// finish until either all the requested data is written, or an error occurs. +NNG_DECL void nng_http_write_all(nng_http *, nng_aio *); -// nng_http_res_get_header looks up a header with the named, returns NULL -// if not found. -NNG_DECL const char *nng_http_res_get_header( - const nng_http_res *, const char *); +// nng_http_write_request writes the entire request. It will also write +// any data that has been attached. +NNG_DECL void nng_http_write_request(nng_http *, nng_aio *); -// nng_http_res_set_version is used to change the version of a response. -// Normally the version is "HTTP/1.1". Note that the framework does -// not support HTTP/2 at all. NULL sets the default ("HTTP/1.1"). -NNG_DECL int nng_http_res_set_version(nng_http_res *, const char *); +// nng_http_write_response writes the entire response. It will also write +// any data that has been attached. It uses the res object in the conn. +NNG_DECL void nng_http_write_response(nng_http *, nng_aio *); -// nng_http_res_get_version returns the version, usually HTTP/1.1. -NNG_DECL const char *nng_http_res_get_version(const nng_http_res *); +// nng_http_read_response reads an entire response, EXCEPT for any entity +// data. The caller is responsible for processing the headers in the response +// and reading any submitted entity data itself. +NNG_DECL void nng_http_read_response(nng_http *, nng_aio *); -// nng_http_res_get_data gets the data for the response. -NNG_DECL void nng_http_res_get_data(nng_http_res *, void **, size_t *); +// nng_http_reset resets the transaction (including headers, URI, etc.) +// and the response. It should be used when reusing the connection. +NNG_DECL void nng_http_reset(nng_http *); -// nng_http_res_set_data adds entity data to the response. The -// data object must persist (so only really useful for static data). -// The content-length header is updated as well, but the caller should -// probably set the content-type header. -NNG_DECL int nng_http_res_set_data(nng_http_res *, const void *, size_t); +// nng_http_set_uri sets the URI associated with the request. It can +// include an optional query string, either inline in the URI to start, +// or as a separate argument. If the query string already exists +// and one is also supplied here, it will be appended (separated with &). +NNG_DECL int nng_http_set_uri(nng_http *, const char *, const char *); -// nng_http_res_copy_data adds entity data to the response. A private -// copy of the data is made (will be freed with the request). -// The content-length header is updated as well, but the caller should -// probably set the content-type header. -NNG_DECL int nng_http_res_copy_data(nng_http_res *, const void *, size_t); +// nng_http_get_uri returns the URI. It will be NULL if not set. +NNG_DECL const char *nng_http_get_uri(nng_http *); -// An nng_http_conn represents an underlying "connection". It may be -// a TCP channel, or a TLS channel, but the main thing is that this is -// normally only used for exchanging HTTP requests and responses. -typedef struct nng_http_conn nng_http_conn; +// nng_http_get_status gets the status of the last transaction +NNG_DECL uint16_t nng_http_get_status(nng_http *); -// 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_reason gets the message associated with status of the last +// transaction +NNG_DECL const char *nng_http_get_reason(nng_http *); -// 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 *); +// nng_http_set_status sets the status for the transaction (server API), +// and also sets the reason (message) for it. (If NULL is used for the reason, +// then a builtin value is used based on the code.) +NNG_DECL int nng_http_set_status(nng_http *, uint16_t, const char *); -// nng_http_conn_read attempts to read data from the connection. This -// completes as soon as at least one byte is read; it does not wait -// for the entire aio to be filled. -NNG_DECL void nng_http_conn_read(nng_http_conn *, nng_aio *); +// nng_http_set_version is used to change the version of a request. +// Normally the version is "HTTP/1.1". Note that the framework does +// not support HTTP/2 at all. Null sets the default ("HTTP/1.1"). +NNG_DECL int nng_http_set_version(nng_http *, const char *); -// nng_http_conn_read_all is like nng_http_conn_read, but it does not -// finish until either all the requested data is read, or an error occurs. -NNG_DECL void nng_http_conn_read_all(nng_http_conn *, nng_aio *); +// nng_http_get_version is used to get the version of a request. +NNG_DECL const char *nng_http_get_version(nng_http *); -// nng_http_conn_write attempts to write data, but it can write less -// than the amount requested. (It completes as soon as at least one -// byte is written.) -NNG_DECL void nng_http_conn_write(nng_http_conn *, nng_aio *); +// nng_http_set_method is used to change the method of a request. +// The method should be an upper case HTTP method, like POST, or DELETE. +// Null sets the default ("GET"). +NNG_DECL void nng_http_set_method(nng_http *, const char *); -// nng_http_conn_write_all is like nng_http_conn_write, but it does not -// finish until either all the requested data is written, or an error occurs. -NNG_DECL void nng_http_conn_write_all(nng_http_conn *, nng_aio *); +// nng_http_get_method returns the method. +NNG_DECL const char *nng_http_get_method(nng_http *); -// nng_http_conn_write_req writes the entire request. It will also write any -// data that has been attached. -NNG_DECL void nng_http_conn_write_req( - nng_http_conn *, nng_http_req *, nng_aio *); +// These functions set (replacing any existing), or add (appending) +// a header to either the request or response. Clients modify the request +// headers, and servers (and callbacks on the server) modify response headers. +// These can return NNG_ENOMEM, NNG_MSGSIZE, etc. +NNG_DECL int nng_http_set_header(nng_http *, const char *, const char *); +NNG_DECL int nng_http_add_header(nng_http *, const char *, const char *); -// nng_http_conn_write_res writes the entire response. It will also write any -// 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_del_header removes all of the headers for the given header. +// For clients this is done on the request headers, for servers its the +// response headers. +NNG_DECL void nng_http_del_header(nng_http *, const char *); -// 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_aio *); +// nng_http_get_header returns the value of the given header. For clients, +// it gets the response header, but for servers it gets the request header. +// It returns NULL if no matching header can be found. +NNG_DECL const char *nng_http_get_header(nng_http *, const char *); -// 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 -// and reading any submitted entity data itself. -NNG_DECL void nng_http_conn_read_res( - nng_http_conn *, nng_http_res *, nng_aio *); +// nng_http_get_body returns the body sent by the peer, if one is attached. +NNG_DECL void nng_http_get_body(nng_http *, void **, size_t *); -// nng_http_req_reset resets the request to an initially allocated state. -NNG_DECL void nng_http_req_reset(nng_http_req *); +// nng_http_set_body sets the body to send out in the next exchange. +NNG_DECL void nng_http_set_body(nng_http *, void *, size_t); -// nng_http_res_reset resets the response to an initially allocated state. -NNG_DECL void nng_http_res_reset(nng_http_res *); +// nng_http_copy_body sets the body to send out in the next exchange, but +// makes a local copy. It can fail due to NNG_ENOMEM. +NNG_DECL int nng_http_copy_body(nng_http *, const void *, size_t); // nng_http_handler is a handler used on the server side to handle HTTP // requests coming into a specific URL. +// typedef struct nng_http_handler nng_http_handler; // nng_http_handler_alloc creates a server handler object, for the supplied @@ -308,18 +225,15 @@ 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 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. +// If the connection is hijacked, then the server will not send any response, +// otherwise it does. // // 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. 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 *); +typedef void (*nng_http_handler_func)(nng_http *, void *, nng_aio *); NNG_DECL int nng_http_handler_alloc( nng_http_handler **, const char *, nng_http_handler_func); @@ -462,11 +376,7 @@ NNG_DECL int nng_http_server_get_addr(nng_http_server *, nng_sockaddr *); // nng_http_server_set_error_page sets a custom error page (HTML) content // to be sent for the given error code. This is used when the error is -// generated internally by the framework, or when the application returns -// the response back to the server via the handler's aio, and the response -// was allocated with nng_http_res_alloc_error. If the response was not -// allocated this way, or the application writes the response itself instead -// of letting the server do so, then this setting will be ignored. +// generated internally by the framework. NNG_DECL int nng_http_server_set_error_page( nng_http_server *, uint16_t, const char *); @@ -480,13 +390,13 @@ NNG_DECL int nng_http_server_set_error_file( // nng_http_server_res_error takes replaces the body of the response with // a custom error page previously set for the server, using the status // of the response. The response must have the status set first using -// nng_http_res_set_status or implicitly via nng_http_res_alloc_error. -NNG_DECL int nng_http_server_res_error(nng_http_server *, nng_http_res *); +// nng_http_res_set_status. +NNG_DECL int nng_http_server_error(nng_http_server *, nng_http *); // nng_http_hijack is intended to be called by a handler that wishes to // take over the processing of the HTTP session -- usually to change protocols // (such as in the case of websocket). The caller is responsible for the -// final disposal of the associated nng_http_conn. Also, this completely +// final disposal of the associated nng_http. Also, this completely // disassociates the http session from the server, so the server may be // stopped or destroyed without affecting the hijacked session. Note also // that the hijacker will need to issue any HTTP reply itself. Finally, @@ -494,7 +404,7 @@ NNG_DECL int nng_http_server_res_error(nng_http_server *, nng_http_res *); // of the request structure. (Some hijackers may keep the request for // further processing.) -NNG_DECL int nng_http_hijack(nng_http_conn *); +NNG_DECL int nng_http_hijack(nng_http *); // nng_http_client represents a "client" object. Clients can be used // to create HTTP connections. At present, connections are not cached @@ -522,24 +432,18 @@ NNG_DECL int nng_http_client_get_tls(nng_http_client *, nng_tls_config **); // nng_http_client_connect establishes a new connection with the server // named in the URL used when the client was created. Once the connection -// is established, the associated nng_http_conn object pointer is returned +// is established, the associated nng_http object pointer is returned // in the first (index 0) output for the aio. NNG_DECL void nng_http_client_connect(nng_http_client *, nng_aio *); -// nng_http_conn_transact is used to perform a round-trip exchange (i.e. a +// nng_http_transact is used to perform a round-trip exchange (i.e. a // 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_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 -// complete. -NNG_DECL void nng_http_client_transact( - nng_http_client *, nng_http_req *, nng_http_res *, nng_aio *); +NNG_DECL void nng_http_transact(nng_http *, nng_aio *); #ifdef __cplusplus } #endif -#endif // NNG_H +#endif // NNG_HTTP_H diff --git a/include/nng/nng.h b/include/nng/nng.h index 5a9f5dbc..6f01363f 100644 --- a/include/nng/nng.h +++ b/include/nng/nng.h @@ -809,23 +809,12 @@ NNG_DECL nng_listener nng_pipe_listener(nng_pipe); // WebSocket Options. -// NNG_OPT_WS_REQUEST_HEADERS is a string containing the -// request headers, formatted as CRLF terminated lines. -#define NNG_OPT_WS_REQUEST_HEADERS "ws:request-headers" - -// NNG_OPT_WS_RESPONSE_HEADERS is a string containing the -// response headers, formatted as CRLF terminated lines. -#define NNG_OPT_WS_RESPONSE_HEADERS "ws:response-headers" - -// NNG_OPT_WS_REQUEST_HEADER is a prefix, for a dynamic -// property name. This allows direct access to any named header. -// Concatenate this with the name of the property (case is not sensitive). -// Only the first such header is returned. -#define NNG_OPT_WS_RESPONSE_HEADER "ws:response-header:" - -// NNG_OPT_WS_RESPONSE_HEADER is like NNG_OPT_REQUEST_HEADER, but used for -// accessing the request headers. -#define NNG_OPT_WS_REQUEST_HEADER "ws:request-header:" +// NNG_OPT_WS_HEADER is a prefix, for a dynamic property name. +// This allows direct access to any named header to set a header on +// a dialer or listener. This property can be used to set headers +// on outgoing dialer or listeners, and can be used to return the +// headers from the peer on a pipe. +#define NNG_OPT_WS_HEADER "ws:header:" // NNG_OPT_WS_REQUEST_URI is used to obtain the URI sent by the client. // This can be useful when a handler supports an entire directory tree. |
