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 API refactoring #2075

Merged
merged 1 commit into from
Jan 10, 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
25 changes: 11 additions & 14 deletions demo/http_client/http_client.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright 2018 Staysail Systems, Inc. <[email protected]>
// Copyright 2025 Staysail Systems, Inc. <[email protected]>
// Copyright 2018 Capitar IT Group BV <[email protected]>
//
// This software is supplied under the terms of the MIT License, a
Expand Down Expand Up @@ -33,8 +33,8 @@
// % ./http_client http://httpbin.org/ip
//

#include <nng/http.h>
#include <nng/nng.h>
#include <nng/supplemental/http/http.h>
#include <stdio.h>
#include <stdlib.h>

Expand All @@ -49,11 +49,9 @@ int
main(int argc, char **argv)
{
nng_http_client *client;
nng_http_conn *conn;
nng_http *conn;
nng_url *url;
nng_aio *aio;
nng_http_req *req;
nng_http_res *res;
const char *hdr;
int rv;
int len;
Expand All @@ -66,12 +64,12 @@ main(int argc, char **argv)
}

if (((rv = nng_init(NULL)) != 0) ||
((rv = nng_aio_alloc(&aio, NULL, NULL)) != 0) ||
((rv = nng_url_parse(&url, argv[1])) != 0) ||
((rv = nng_http_client_alloc(&client, url)) != 0) ||
((rv = nng_http_req_alloc(&req, url)) != 0) ||
((rv = nng_http_res_alloc(&res)) != 0) ||
((rv = nng_aio_alloc(&aio, NULL, NULL)) != 0)) {
fatal(rv);
return 1;
}

// Start connection process...
Expand All @@ -90,30 +88,29 @@ main(int argc, char **argv)
// The Host: header is already set up too.

// Send the request, and wait for that to finish.
nng_http_conn_write_req(conn, req, aio);
nng_http_write_request(conn, aio);
nng_aio_wait(aio);

if ((rv = nng_aio_result(aio)) != 0) {
fatal(rv);
}

// Read a response.
nng_http_conn_read_res(conn, res, aio);
nng_http_read_response(conn, aio);
nng_aio_wait(aio);

if ((rv = nng_aio_result(aio)) != 0) {
fatal(rv);
}

if (nng_http_res_get_status(res) != NNG_HTTP_STATUS_OK) {
if (nng_http_get_status(conn) != NNG_HTTP_STATUS_OK) {
fprintf(stderr, "HTTP Server Responded: %d %s\n",
nng_http_res_get_status(res),
nng_http_res_get_reason(res));
nng_http_get_status(conn), nng_http_get_reason(conn));
}

// This only supports regular transfer encoding (no Chunked-Encoding,
// and a Content-Length header is required.)
if ((hdr = nng_http_res_get_header(res, "Content-Length")) == NULL) {
if ((hdr = nng_http_get_header(conn, "Content-Length")) == NULL) {
fprintf(stderr, "Missing Content-Length header.\n");
exit(1);
}
Expand All @@ -134,7 +131,7 @@ main(int argc, char **argv)
nng_aio_set_iov(aio, 1, &iov);

// Now attempt to receive the data.
nng_http_conn_read_all(conn, aio);
nng_http_read_all(conn, aio);

// Wait for it to complete.
nng_aio_wait(aio);
Expand Down
1 change: 0 additions & 1 deletion demo/reqrep/reqrep.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ client(const char *url)
nng_socket sock;
nng_dialer dialer;
int rv;
size_t sz;
int sleep = 0;

if ((rv = nng_init(NULL)) != 0) {
Expand Down
63 changes: 21 additions & 42 deletions demo/rest/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,8 @@
// GRFG
//

#include <nng/http.h>
#include <nng/nng.h>
#include <nng/protocol/reqrep0/rep.h>
#include <nng/protocol/reqrep0/req.h>
#include <nng/supplemental/http/http.h>
#include <nng/supplemental/util/platform.h>

#include <ctype.h>
#include <stdio.h>
Expand Down Expand Up @@ -74,12 +71,12 @@ typedef enum {

typedef struct rest_job {
nng_aio *http_aio; // aio from HTTP we must reply to
nng_http_res *http_res; // HTTP response object
job_state state; // 0 = sending, 1 = receiving
nng_msg *msg; // request message
nng_aio *aio; // request flow
nng_ctx ctx; // context on the request socket
struct rest_job *next; // next on the freelist
nng_http *conn;
struct rest_job *next; // next on the freelist
} rest_job;

nng_socket req_sock;
Expand All @@ -94,10 +91,6 @@ static void rest_job_cb(void *arg);
static void
rest_recycle_job(rest_job *job)
{
if (job->http_res != NULL) {
nng_http_res_free(job->http_res);
job->http_res = NULL;
}
if (job->msg != NULL) {
nng_msg_free(job->msg);
job->msg = NULL;
Expand Down Expand Up @@ -136,20 +129,13 @@ rest_get_job(void)
}

static void
rest_http_fatal(rest_job *job, const char *fmt, int rv)
rest_http_fatal(rest_job *job, int rv)
{
char buf[128];
nng_aio *aio = job->http_aio;
nng_http_res *res = job->http_res;

job->http_res = NULL;
job->http_aio = NULL;
snprintf(buf, sizeof(buf), fmt, nng_strerror(rv));
nng_http_res_set_status(res, NNG_HTTP_STATUS_INTERNAL_SERVER_ERROR);
nng_http_res_set_reason(res, buf);

nng_aio_set_output(aio, 0, res);
nng_aio_finish(aio, 0);
nng_aio *aio = job->http_aio;

// let the server give the details, we could have done more here
// ourselves if we wanted a detailed message
nng_aio_finish(aio, rv);
rest_recycle_job(job);
}

Expand All @@ -163,7 +149,7 @@ rest_job_cb(void *arg)
switch (job->state) {
case SEND_REQ:
if ((rv = nng_aio_result(aio)) != 0) {
rest_http_fatal(job, "send REQ failed: %s", rv);
rest_http_fatal(job, rv);
return;
}
job->msg = NULL;
Expand All @@ -174,23 +160,20 @@ rest_job_cb(void *arg)
break;
case RECV_REP:
if ((rv = nng_aio_result(aio)) != 0) {
rest_http_fatal(job, "recv reply failed: %s", rv);
rest_http_fatal(job, rv);
return;
}
job->msg = nng_aio_get_msg(aio);
// We got a reply, so give it back to the server.
rv = nng_http_res_copy_data(job->http_res,
nng_msg_body(job->msg), nng_msg_len(job->msg));
rv = nng_http_copy_body(
job->conn, nng_msg_body(job->msg), nng_msg_len(job->msg));
if (rv != 0) {
rest_http_fatal(job, "nng_http_res_copy_data: %s", rv);
rest_http_fatal(job, rv);
return;
}
// Set the output - the HTTP server will send it back to the
// user agent with a 200 response.
nng_aio_set_output(job->http_aio, 0, job->http_res);
nng_http_set_status(job->conn, NNG_HTTP_STATUS_OK, NULL);
nng_aio_finish(job->http_aio, 0);
job->http_aio = NULL;
job->http_res = NULL;
// We are done with the job.
rest_recycle_job(job);
return;
Expand All @@ -203,33 +186,29 @@ rest_job_cb(void *arg)
// Our rest server just takes the message body, creates a request ID
// for it, and sends it on. This runs in raw mode, so
void
rest_handle(nng_aio *aio)
rest_handle(nng_http *conn, void *arg, nng_aio *aio)
{
struct rest_job *job;
nng_http_req *req = nng_aio_get_input(aio, 0);
nng_http_conn *conn = nng_aio_get_input(aio, 2);
const char *clen;
size_t sz;
nng_iov iov;
int rv;
void *data;

if ((job = rest_get_job()) == NULL) {
nng_aio_finish(aio, NNG_ENOMEM);
return;
}
if (((rv = nng_http_res_alloc(&job->http_res)) != 0) ||
((rv = nng_ctx_open(&job->ctx, req_sock)) != 0)) {
job->conn = conn;
if (((rv = nng_ctx_open(&job->ctx, req_sock)) != 0)) {
rest_recycle_job(job);
nng_aio_finish(aio, rv);
return;
}

nng_http_req_get_data(req, &data, &sz);
nng_http_get_body(conn, &data, &sz);
job->http_aio = aio;

if ((rv = nng_msg_alloc(&job->msg, sz)) != 0) {
rest_http_fatal(job, "nng_msg_alloc: %s", rv);
rest_http_fatal(job, rv);
return;
}

Expand Down Expand Up @@ -329,7 +308,7 @@ inproc_server(void *arg)
fatal("inproc recvmsg", rv);
}
body = nng_msg_body(msg);
for (int i = 0; i < nng_msg_len(msg); i++) {
for (size_t i = 0; i < nng_msg_len(msg); i++) {
// Table lookup would be faster, but this works.
if (isupper(body[i])) {
char base = body[i] - 'A';
Expand Down
39 changes: 0 additions & 39 deletions docs/man/libnng.3.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -99,61 +99,23 @@ The following functions are used to work with HTTP requests, responses,
and connections.

|===
|xref:nng_http_conn_close.3http.adoc[nng_http_conn_close()]|close HTTP connection
|xref:nng_http_conn_read.3http.adoc[nng_http_conn_read()]|read from HTTP connection
|xref:nng_http_conn_read_all.3http.adoc[nng_http_conn_read_all()]|read all from HTTP connection
|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.3http.adoc[nng_http_conn_write()]|write to HTTP connection
|xref:nng_http_conn_write_all.3http.adoc[nng_http_conn_write_all()]|write all to HTTP connection
|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_add_header.3http.adoc[nng_http_req_add_header()]|add HTTP request header
|xref:nng_http_req_alloc.3http.adoc[nng_http_req_alloc()]|allocate HTTP request structure
|xref:nng_http_req_copy_data.3http.adoc[nng_http_req_copy_data()]|copy HTTP request body
|xref:nng_http_req_del_header.3http.adoc[nng_http_req_del_header()]|delete HTTP request header
|xref:nng_http_req_free.3http.adoc[nng_http_req_free()]|free HTTP request structure
|xref:nng_http_req_get_data.3http.adoc[nng_http_req_get_data()]|get HTTP request body
|xref:nng_http_req_get_header.3http.adoc[nng_http_req_get_header()]|return HTTP request header
|xref:nng_http_req_get_method.3http.adoc[nng_http_req_get_method()]|return HTTP request method
|xref:nng_http_req_get_uri.3http.adoc[nng_http_req_get_uri()]|return HTTP request URI
|xref:nng_http_req_get_version.3http.adoc[nng_http_req_get_version()]|return HTTP request protocol version
|xref:nng_http_req_reset.3http.adoc[nng_http_req_reset()]|reset HTTP request structure
|xref:nng_http_req_set_data.3http.adoc[nng_http_req_set_data()]|set HTTP request body
|xref:nng_http_req_set_header.3http.adoc[nng_http_req_set_header()]|set HTTP request header
|xref:nng_http_req_set_method.3http.adoc[nng_http_req_set_method()]|set HTTP request method
|xref:nng_http_req_set_uri.3http.adoc[nng_http_req_set_uri()]|set HTTP request URI
|xref:nng_http_req_set_version.3http.adoc[nng_http_req_set_version()]|set HTTP request protocol version
|xref:nng_http_res_add_header.3http.adoc[nng_http_res_add_header()]|add HTTP response header
|xref:nng_http_res_alloc.3http.adoc[nng_http_res_alloc()]|allocate HTTP response structure
|xref:nng_http_res_alloc_error.3http.adoc[nng_http_res_alloc_error()]|allocate HTTP error response
|xref:nng_http_res_copy_data.3http.adoc[nng_http_res_copy_data()]|copy HTTP response body
|xref:nng_http_res_del_header.3http.adoc[nng_http_res_del_header()]|delete HTTP response header
|xref:nng_http_res_free.3http.adoc[nng_http_res_free()]|free HTTP response structure
|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_get_reason.3http.adoc[nng_http_res_get_reason()]|return HTTP response reason
|xref:nng_http_res_get_status.3http.adoc[nng_http_res_get_status()]|return HTTP response status
|xref:nng_http_res_get_version.3http.adoc[nng_http_res_get_version()]|return HTTP response protocol version
|xref:nng_http_res_reset.3http.adoc[nng_http_res_reset()]|reset HTTP response structure
|xref:nng_http_res_set_data.3http.adoc[nng_http_res_set_data()]|set HTTP response body
|xref:nng_http_res_set_header.3http.adoc[nng_http_res_set_header()]|set HTTP response header
|xref:nng_http_res_set_reason.3http.adoc[nng_http_res_set_reason()]|set HTTP response reason
|xref:nng_http_res_set_status.3http.adoc[nng_http_res_set_status()]|set HTTP response status
|xref:nng_http_res_set_version.3http.adoc[nng_http_res_set_version()]|set HTTP response protocol version
|===

==== HTTP Client Functions

These functions are intended for use with HTTP client applications.

|===
|xref:nng_http_client_alloc.3http.adoc[nng_http_client_alloc()]|allocate HTTP client
|xref:nng_http_client_connect.3http.adoc[nng_http_client_connect()]|establish HTTP client connection
|xref:nng_http_client_free.3http.adoc[nng_http_client_free()]|free HTTP client
|xref:nng_http_client_get_tls.3http.adoc[nng_http_client_get_tls()]|get HTTP client TLS configuration
|xref:nng_http_client_set_tls.3http.adoc[nng_http_client_set_tls()]|set HTTP client TLS configuration
|xref:nng_http_client_transact.3http.adoc[nng_http_client_transact()]|perform one HTTP transaction
|xref:nng_http_conn_transact.3http.adoc[nng_http_conn_transact()]|perform one HTTP transaction on connection
|===

Expand All @@ -170,7 +132,6 @@ These functions are intended for use with HTTP server applications.
|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
|xref:nng_http_handler_set_tree.3http.adoc[nng_http_handler_set_tree()]|set HTTP handler to match trees
|xref:nng_http_hijack.3http.adoc[nng_http_hijack()]|hijack HTTP server connection
|xref:nng_http_server_add_handler.3http.adoc[nng_http_server_add_handler()]|add HTTP server handler
|xref:nng_http_server_del_handler.3http.adoc[nng_http_server_del_handler()]|delete HTTP server handler
|xref:nng_http_server_get_addr.3http.adoc[nng_http_server_get_addr()]|get HTTP server address
Expand Down
1 change: 0 additions & 1 deletion docs/man/nng.7.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ xref:nng_socket.7.adoc[nng_socket(7)]:: BSD socket transport
xref:nng_tls.7.adoc[nng_tls(7)]:: TLSv1.2 over TCP transport
xref:nng_tcp.7.adoc[nng_tcp(7)]:: TCP (and TCPv6) transport
xref:nng_ws.7.adoc[nng_ws(7)]:: WebSocket transport
xref:nng_zerotier.7.adoc[nng_zerotier(7)]:: ZeroTier transport

=== Conceptual Overview

Expand Down
49 changes: 0 additions & 49 deletions docs/man/nng_http_client_alloc.3http.adoc

This file was deleted.

Loading
Loading