Skip to content
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
2 changes: 2 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
Version 0.20.0

Added example and documentation for serving binary data from memory
using string_response (addresses PR #368).
Added conditional compilation for basic auth (HAVE_BAUTH), mirroring
existing HAVE_DAUTH pattern for digest auth. Basic auth support
is auto-detected via AC_CHECK_LIB and can be disabled at build time.
Expand Down
37 changes: 36 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -807,7 +807,7 @@ You can also check this example on [github](https://github.com/etr/libhttpserver
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.

There are 5 types of response that you can create - we will describe them here through their constructors:
* _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.
* _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"`).
* _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.
* _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.
* _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.
Expand Down Expand Up @@ -856,6 +856,41 @@ You will receive the message custom header in reply.

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

### Serving binary data from memory
`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.

```cpp
#include <httpserver.hpp>

using namespace httpserver;

class image_resource : public http_resource {
public:
std::shared_ptr<http_response> render_GET(const http_request&) {
// binary_data could come from a camera capture, image library, etc.
std::string binary_data = get_image_bytes_from_camera();

return std::make_shared<string_response>(
std::move(binary_data), 200, "image/jpeg");
}
};

int main() {
webserver ws = create_webserver(8080);

image_resource ir;
ws.register_resource("/image", &ir);
ws.start(true);

return 0;
}
```
To test the above example, you could run the following command from a terminal:

curl -o image.jpg http://localhost:8080/image

You can also check the complete example on [github](https://github.com/etr/libhttpserver/blob/master/examples/binary_buffer_response.cpp).

[Back to TOC](#table-of-contents)

## IP Blacklisting and Whitelisting
Expand Down
3 changes: 2 additions & 1 deletion examples/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
LDADD = $(top_builddir)/src/libhttpserver.la
AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/httpserver/
METASOURCES = AUTO
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
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

hello_world_SOURCES = hello_world.cpp
service_SOURCES = service.cpp
Expand All @@ -42,6 +42,7 @@ benchmark_threads_SOURCES = benchmark_threads.cpp
benchmark_nodelay_SOURCES = benchmark_nodelay.cpp
file_upload_SOURCES = file_upload.cpp
file_upload_with_callback_SOURCES = file_upload_with_callback.cpp
binary_buffer_response_SOURCES = binary_buffer_response.cpp

if HAVE_BAUTH
noinst_PROGRAMS += basic_authentication centralized_authentication
Expand Down
82 changes: 82 additions & 0 deletions examples/binary_buffer_response.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
This file is part of libhttpserver
Copyright (C) 2011, 2012, 2013, 2014, 2015 Sebastiano Merlino

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
*/

// This example demonstrates how to serve binary data (e.g., images) directly
// from an in-memory buffer using string_response. Despite its name,
// string_response works with arbitrary binary content because std::string can
// hold any bytes, including null characters.
//
// This is useful when you generate or receive binary data at runtime (e.g.,
// from a camera, an image library, or a database) and want to serve it over
// HTTP without writing it to disk first.
//
// To test:
// curl -o output.png http://localhost:8080/image

#include <memory>
#include <string>
#include <utility>

#include <httpserver.hpp>

// Generate a minimal valid 1x1 red PNG image in memory.
// In a real application, this could come from a camera capture, image
// processing library, database blob, etc.
static std::string generate_png_data() {
// Minimal 1x1 red pixel PNG (68 bytes)
static const unsigned char png[] = {
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, // PNG signature
0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, // IHDR chunk
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, // 1x1
0x08, 0x02, 0x00, 0x00, 0x00, 0x90, 0x77, 0x53, // 8-bit RGB
0xde, 0x00, 0x00, 0x00, 0x0c, 0x49, 0x44, 0x41, // IDAT chunk
0x54, 0x08, 0xd7, 0x63, 0xf8, 0xcf, 0xc0, 0x00, // compressed data
0x00, 0x00, 0x03, 0x00, 0x01, 0x36, 0x28, 0x19,
0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, // IEND chunk
0x44, 0xae, 0x42, 0x60, 0x82
};

return std::string(reinterpret_cast<const char*>(png), sizeof(png));
}

class image_resource : public httpserver::http_resource {
public:
std::shared_ptr<httpserver::http_response> render_GET(const httpserver::http_request&) {
// Build binary content as a std::string. The string can contain any
// bytes — it is not limited to printable characters or null-terminated
// C strings. The size is tracked internally by std::string::size().
std::string image_data = generate_png_data();

// Use string_response with the appropriate content type. The response
// will send the exact bytes contained in the string.
return std::make_shared<httpserver::string_response>(
std::move(image_data), 200, "image/png");
}
};

int main() {
httpserver::webserver ws = httpserver::create_webserver(8080);

image_resource ir;
ws.register_resource("/image", &ir);
ws.start(true);

return 0;
}
Loading