#include #include // This example shows how to generate response bodies // using the zero-copy API. int main(void) { http_global_init(); // All the setup is identical to the previous example. // The only thing that changes where "http_response_builder_body" // is called. HTTP_Server *server = http_server_init(HTTP_STR("127.0.0.1"), 8080); if (server == NULL) return -1; for (;;) { HTTP_Request *req; HTTP_ResponseBuilder builder; int ret = http_server_wait(server, &req, &builder); if (ret < 0) return -1; http_response_builder_status(builder, 200); http_response_builder_header(builder, HTTP_STR("Content-Type: text/plain")); // The previous example used the *_body function to // write the response body in chunks: // // http_response_builder_body(builder, HTTP_STR("Hello")); // http_response_builder_body(builder, HTTP_STR(", world!")); // // This function reads from an user buffer and copies // the data in the connection's output buffer. If the // data is not in a contiguous region that's fine as // the function can be called repeatedly on separate // chunks. // // This function assumes the user is holding in memory // the data to be sent beforehand, but this may not // be true. If for instance the data comes from a file, // the user will need to read from the file, copy in // memory and then write to the response body. // // The zero-copy API allows copying directly from the // source of the data (such as the read() system call // on a file descriptor) to the server's output buffer char example_data[] = "I'm some example data!"; int example_data_len = sizeof(example_data)-1; // Tell the server how much data we are going to write http_response_builder_bodycap(builder, example_data_len); int cap; char *dst; // Get a pointer to the server's output buffer. The // output parameter [cap] is the capacity of the region // and is equal or larger than the data we requested // with *_bodycap dst = http_response_builder_bodybuf(builder, &cap); // Write the data directly into the output buffer. In // this example we are copying from memory, but you could // read from a file or a socket if (dst) { memcpy(dst, example_data, example_data_len); } // Tell the server how much bytes we have written to // the provided region. http_response_builder_bodyack(builder, example_data_len); // The reason we had to guard the [memcpy] by checking the // [dst] pointer is that if an error occurred internally // then *_bodybuf will return NULL. This will cause the // server to either return an internally generated error // response or drop the connection. The correct thing to // do in that situation is not access the pointer and do // as nothing bad happened. // As usual, mark the response as complete http_response_builder_done(builder); // If we're being being honest, this is not a zero-copy // interface. It's more like an N-1 copy interface as in // it just avoids one copy from userspace to userspace! } http_server_free(server); http_global_free(); return 0; }