Skip to content

Commit 97bd4b1

Browse files
committed
Add documentation and example for serving binary data from memory
The existing string_response already supports binary content (std::string can hold arbitrary bytes), but this was not documented or demonstrated anywhere. This gap caused users to believe a new response type was needed (see PR #368). - Add a note to the README's string_response description clarifying binary data support - Add a new "Serving binary data from memory" section with inline example - Add examples/binary_buffer_response.cpp as a complete, buildable example that serves a PNG image from an in-memory buffer - Register the new example in examples/Makefile.am https://claude.ai/code/session_01S3BvBrSoNvUhpYTyhPYCjJ
1 parent 68bff78 commit 97bd4b1

File tree

3 files changed

+119
-2
lines changed

3 files changed

+119
-2
lines changed

README.md

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -807,7 +807,7 @@ You can also check this example on [github](https://github.com/etr/libhttpserver
807807
As seen in the documentation of [http_resource](#the-resource-object), every extensible method returns in output a `http_response` object. The webserver takes the responsibility to convert the `http_response` object you create into a response on the network.
808808

809809
There are 5 types of response that you can create - we will describe them here through their constructors:
810-
* _string_response(**const std::string&** content, **int** response_code = `200`, **const std::string&** content_type = `"text/plain"`):_ The most basic type of response. It uses the `content` string passed in construction as body of the HTTP response. The other two optional parameters are the `response_code` and the `content_type`. You can find constant definition for the various response codes within the [http_utils](https://github.com/etr/libhttpserver/blob/master/src/httpserver/http_utils.hpp) library file.
810+
* _string_response(**const std::string&** content, **int** response_code = `200`, **const std::string&** content_type = `"text/plain"`):_ The most basic type of response. It uses the `content` string passed in construction as body of the HTTP response. The other two optional parameters are the `response_code` and the `content_type`. You can find constant definition for the various response codes within the [http_utils](https://github.com/etr/libhttpserver/blob/master/src/httpserver/http_utils.hpp) library file. Note that `std::string` can hold arbitrary binary data (including null bytes), so `string_response` is also the right choice for serving binary content such as images directly from memory — simply set an appropriate `content_type` (e.g., `"image/png"`).
811811
* _file_response(**const std::string&** filename, **int** response_code = `200`, **const std::string&** content_type = `"text/plain"`):_ Uses the `filename` passed in construction as pointer to a file on disk. The body of the HTTP response will be set using the content of the file. The file must be a regular file and exist on disk. Otherwise libhttpserver will return an error 500 (Internal Server Error). The other two optional parameters are the `response_code` and the `content_type`. You can find constant definition for the various response codes within the [http_utils](https://github.com/etr/libhttpserver/blob/master/src/httpserver/http_utils.hpp) library file.
812812
* _basic_auth_fail_response(**const std::string&** content, **const std::string&** realm = `""`, **int** response_code = `200`, **const std::string&** content_type = `"text/plain"`):_ A response in return to a failure during basic authentication. It allows to specify a `content` string as a message to send back to the client. The `realm` parameter should contain your realm of authentication (if any). The other two optional parameters are the `response_code` and the `content_type`. You can find constant definition for the various response codes within the [http_utils](https://github.com/etr/libhttpserver/blob/master/src/httpserver/http_utils.hpp) library file.
813813
* _digest_auth_fail_response(**const std::string&** content, **const std::string&** realm = `""`, **const std::string&** opaque = `""`, **bool** reload_nonce = `false`, **int** response_code = `200`, **const std::string&** content_type = `"text/plain"`):_ A response in return to a failure during digest authentication. It allows to specify a `content` string as a message to send back to the client. The `realm` parameter should contain your realm of authentication (if any). The `opaque` represents a value that gets passed to the client and expected to be passed again to the server as-is. This value can be a hexadecimal or base64 string. The `reload_nonce` parameter tells the server to reload the nonce (you should use the value returned by the `check_digest_auth` method on the `http_request`. The other two optional parameters are the `response_code` and the `content_type`. You can find constant definition for the various response codes within the [http_utils](https://github.com/etr/libhttpserver/blob/master/src/httpserver/http_utils.hpp) library file.
@@ -856,6 +856,41 @@ You will receive the message custom header in reply.
856856

857857
You can also check this example on [github](https://github.com/etr/libhttpserver/blob/master/examples/setting_headers.cpp).
858858

859+
### Serving binary data from memory
860+
`string_response` is not limited to text — it can serve arbitrary binary content directly from memory. This is useful when you have data in a buffer at runtime (e.g., from a camera, an image processing library, or a database) and want to serve it without writing to disk.
861+
862+
```cpp
863+
#include <httpserver.hpp>
864+
865+
using namespace httpserver;
866+
867+
class image_resource : public http_resource {
868+
public:
869+
std::shared_ptr<http_response> render_GET(const http_request&) {
870+
// binary_data could come from a camera capture, image library, etc.
871+
std::string binary_data = get_image_bytes_from_camera();
872+
873+
return std::make_shared<string_response>(
874+
std::move(binary_data), 200, "image/jpeg");
875+
}
876+
};
877+
878+
int main() {
879+
webserver ws = create_webserver(8080);
880+
881+
image_resource ir;
882+
ws.register_resource("/image", &ir);
883+
ws.start(true);
884+
885+
return 0;
886+
}
887+
```
888+
To test the above example, you could run the following command from a terminal:
889+
890+
curl -o image.jpg http://localhost:8080/image
891+
892+
You can also check the complete example on [github](https://github.com/etr/libhttpserver/blob/master/examples/binary_buffer_response.cpp).
893+
859894
[Back to TOC](#table-of-contents)
860895
861896
## IP Blacklisting and Whitelisting

examples/Makefile.am

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
LDADD = $(top_builddir)/src/libhttpserver.la
2020
AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/httpserver/
2121
METASOURCES = AUTO
22-
noinst_PROGRAMS = hello_world service minimal_hello_world custom_error allowing_disallowing_methods handlers hello_with_get_arg args_processing setting_headers custom_access_log minimal_https minimal_file_response minimal_deferred url_registration minimal_ip_ban benchmark_select benchmark_threads benchmark_nodelay deferred_with_accumulator file_upload file_upload_with_callback
22+
noinst_PROGRAMS = hello_world service minimal_hello_world custom_error allowing_disallowing_methods handlers hello_with_get_arg args_processing setting_headers custom_access_log minimal_https minimal_file_response minimal_deferred url_registration minimal_ip_ban benchmark_select benchmark_threads benchmark_nodelay deferred_with_accumulator file_upload file_upload_with_callback binary_buffer_response
2323

2424
hello_world_SOURCES = hello_world.cpp
2525
service_SOURCES = service.cpp
@@ -42,6 +42,7 @@ benchmark_threads_SOURCES = benchmark_threads.cpp
4242
benchmark_nodelay_SOURCES = benchmark_nodelay.cpp
4343
file_upload_SOURCES = file_upload.cpp
4444
file_upload_with_callback_SOURCES = file_upload_with_callback.cpp
45+
binary_buffer_response_SOURCES = binary_buffer_response.cpp
4546

4647
if HAVE_BAUTH
4748
noinst_PROGRAMS += basic_authentication centralized_authentication
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
This file is part of libhttpserver
3+
Copyright (C) 2011, 2012, 2013, 2014, 2015 Sebastiano Merlino
4+
5+
This library is free software; you can redistribute it and/or
6+
modify it under the terms of the GNU Lesser General Public
7+
License as published by the Free Software Foundation; either
8+
version 2.1 of the License, or (at your option) any later version.
9+
10+
This library is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public
16+
License along with this library; if not, write to the Free Software
17+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
18+
USA
19+
*/
20+
21+
// This example demonstrates how to serve binary data (e.g., images) directly
22+
// from an in-memory buffer using string_response. Despite its name,
23+
// string_response works with arbitrary binary content because std::string can
24+
// hold any bytes, including null characters.
25+
//
26+
// This is useful when you generate or receive binary data at runtime (e.g.,
27+
// from a camera, an image library, or a database) and want to serve it over
28+
// HTTP without writing it to disk first.
29+
//
30+
// To test:
31+
// curl -o output.png http://localhost:8080/image
32+
33+
#include <memory>
34+
#include <string>
35+
36+
#include <httpserver.hpp>
37+
38+
// Generate a minimal valid 1x1 red PNG image in memory.
39+
// In a real application, this could come from a camera capture, image
40+
// processing library, database blob, etc.
41+
static std::string generate_png_data() {
42+
// Minimal 1x1 red pixel PNG (68 bytes)
43+
static const unsigned char png[] = {
44+
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, // PNG signature
45+
0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, // IHDR chunk
46+
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, // 1x1
47+
0x08, 0x02, 0x00, 0x00, 0x00, 0x90, 0x77, 0x53, // 8-bit RGB
48+
0xde, 0x00, 0x00, 0x00, 0x0c, 0x49, 0x44, 0x41, // IDAT chunk
49+
0x54, 0x08, 0xd7, 0x63, 0xf8, 0xcf, 0xc0, 0x00, // compressed data
50+
0x00, 0x00, 0x03, 0x00, 0x01, 0x36, 0x28, 0x19,
51+
0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, // IEND chunk
52+
0x44, 0xae, 0x42, 0x60, 0x82
53+
};
54+
55+
return std::string(reinterpret_cast<const char*>(png), sizeof(png));
56+
}
57+
58+
class image_resource : public httpserver::http_resource {
59+
public:
60+
std::shared_ptr<httpserver::http_response> render_GET(const httpserver::http_request&) {
61+
// Build binary content as a std::string. The string can contain any
62+
// bytes — it is not limited to printable characters or null-terminated
63+
// C strings. The size is tracked internally by std::string::size().
64+
std::string image_data = generate_png_data();
65+
66+
// Use string_response with the appropriate content type. The response
67+
// will send the exact bytes contained in the string.
68+
return std::make_shared<httpserver::string_response>(
69+
std::move(image_data), 200, "image/png");
70+
}
71+
};
72+
73+
int main() {
74+
httpserver::webserver ws = httpserver::create_webserver(8080);
75+
76+
image_resource ir;
77+
ws.register_resource("/image", &ir);
78+
ws.start(true);
79+
80+
return 0;
81+
}

0 commit comments

Comments
 (0)