Skip to content

Commit 71d60e8

Browse files
committed
Add serve_static middleware and support algorithms
1 parent e92e356 commit 71d60e8

29 files changed

Lines changed: 2820 additions & 37 deletions

.cursor/rules/doc.mdc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
description: Documentation style conventions for code snippets, javadocs, and API documentation examples
3+
globs:
4+
alwaysApply: false
5+
---
6+
7+
- `route_params` are named `rp`
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
//
2+
// Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot com)
3+
//
4+
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5+
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6+
//
7+
// Official repository: https://github.com/cppalliance/http
8+
//
9+
10+
#ifndef BOOST_HTTP_DETAIL_ANY_BUFREF_HPP
11+
#define BOOST_HTTP_DETAIL_ANY_BUFREF_HPP
12+
13+
#include <boost/http/detail/config.hpp>
14+
#include <boost/capy/buffers.hpp>
15+
#include <cstddef>
16+
17+
namespace boost {
18+
namespace http {
19+
namespace detail {
20+
21+
/** A type-erased const buffer sequence reference.
22+
23+
This class provides a type-erased interface for iterating
24+
over buffer sequences without knowing the concrete type.
25+
*/
26+
class any_bufref
27+
{
28+
public:
29+
/** Construct from a const buffer sequence.
30+
31+
@param bs The buffer sequence to adapt.
32+
*/
33+
template<capy::ConstBufferSequence BS>
34+
explicit
35+
any_bufref(BS const& bs) noexcept
36+
: bs_(&bs)
37+
, fn_(&copy_impl<BS>)
38+
{
39+
}
40+
41+
/** Fill an array with buffers from the sequence.
42+
43+
@param dest Pointer to array of mutable buffer descriptors.
44+
45+
@param n Maximum number of buffers to copy.
46+
47+
@return The number of buffers actually copied.
48+
*/
49+
std::size_t
50+
copy_to(
51+
capy::mutable_buffer* dest,
52+
std::size_t n) const noexcept
53+
{
54+
return fn_(bs_, dest, n);
55+
}
56+
57+
private:
58+
template<capy::ConstBufferSequence BS>
59+
static std::size_t
60+
copy_impl(
61+
void const* p,
62+
capy::mutable_buffer* dest,
63+
std::size_t n)
64+
{
65+
auto const& bs = *static_cast<BS const*>(p);
66+
auto it = capy::begin(bs);
67+
auto const end_it = capy::end(bs);
68+
69+
std::size_t i = 0;
70+
for(; it != end_it && i < n; ++it, ++i)
71+
{
72+
auto const& buf = *it;
73+
dest[i] = capy::mutable_buffer(
74+
const_cast<char*>(
75+
static_cast<char const*>(buf.data())),
76+
buf.size());
77+
}
78+
return i;
79+
}
80+
81+
using fn_t = std::size_t(*)(void const*,
82+
capy::mutable_buffer*, std::size_t);
83+
84+
void const* bs_;
85+
fn_t fn_;
86+
};
87+
88+
} // detail
89+
} // http
90+
} // boost
91+
92+
#endif

include/boost/http/server/cors.hpp

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,31 +18,73 @@
1818
namespace boost {
1919
namespace http {
2020

21+
/** Options for CORS middleware configuration.
22+
*/
2123
struct cors_options
2224
{
25+
/// Allowed origin, or "*" for any. Empty defaults to "*".
2326
std::string origin;
27+
28+
/// Allowed HTTP methods. Empty defaults to common methods.
2429
std::string methods;
30+
31+
/// Allowed request headers.
2532
std::string allowedHeaders;
33+
34+
/// Response headers exposed to client.
2635
std::string exposedHeaders;
36+
37+
/// Max age for preflight cache.
2738
std::chrono::seconds max_age{ 0 };
39+
40+
/// Status code for preflight response.
2841
status result = status::no_content;
42+
43+
/// If true, pass preflight to next handler.
2944
bool preFlightContinue = false;
45+
46+
/// If true, allow credentials.
3047
bool credentials = false;
3148
};
3249

33-
class cors
50+
/** CORS middleware for handling cross-origin requests.
51+
52+
This middleware handles Cross-Origin Resource Sharing
53+
(CORS) by setting appropriate response headers and
54+
handling preflight OPTIONS requests.
55+
56+
@par Example
57+
@code
58+
cors_options opts;
59+
opts.origin = "*";
60+
opts.methods = "GET,POST,PUT,DELETE";
61+
opts.credentials = true;
62+
63+
router.use( cors( opts ) );
64+
@endcode
65+
66+
@see cors_options
67+
*/
68+
class BOOST_HTTP_DECL cors
3469
{
70+
cors_options options_;
71+
3572
public:
36-
BOOST_HTTP_DECL
37-
explicit cors(
38-
cors_options options = {}) noexcept;
73+
/** Construct a CORS middleware.
3974
40-
BOOST_HTTP_DECL
41-
route_result
42-
operator()(route_params& p) const;
75+
@param options Configuration options.
76+
*/
77+
explicit cors(cors_options options = {}) noexcept;
4378

44-
private:
45-
cors_options options_;
79+
/** Handle a request.
80+
81+
Sets CORS headers and handles preflight requests.
82+
83+
@param rp The route parameters.
84+
85+
@return A task that completes with the routing result.
86+
*/
87+
route_task operator()(route_params& rp) const;
4688
};
4789

4890
} // http
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//
2+
// Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot com)
3+
//
4+
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5+
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6+
//
7+
// Official repository: https://github.com/cppalliance/http
8+
//
9+
10+
#ifndef BOOST_HTTP_SERVER_ENCODE_URL_HPP
11+
#define BOOST_HTTP_SERVER_ENCODE_URL_HPP
12+
13+
#include <boost/http/detail/config.hpp>
14+
#include <boost/core/detail/string_view.hpp>
15+
#include <string>
16+
17+
namespace boost {
18+
namespace http {
19+
20+
/** Percent-encode a URL for safe use in HTTP responses.
21+
22+
Encodes characters that are not safe in URLs using
23+
percent-encoding (e.g. space becomes %20). This is
24+
useful for encoding URLs that will be included in
25+
Location headers or HTML links.
26+
27+
The following characters are NOT encoded:
28+
- Unreserved: A-Z a-z 0-9 - _ . ~
29+
- Reserved (allowed in URLs): ! # $ & ' ( ) * + , / : ; = ? @
30+
31+
@par Example
32+
@code
33+
std::string url = encode_url( "/path/to/file with spaces.txt" );
34+
// url == "/path/to/file%20with%20spaces.txt"
35+
@endcode
36+
37+
@param url The URL or URL component to encode.
38+
39+
@return A new string with unsafe characters percent-encoded.
40+
*/
41+
BOOST_HTTP_DECL
42+
std::string
43+
encode_url(core::string_view url);
44+
45+
} // http
46+
} // boost
47+
48+
#endif
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
//
2+
// Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot com)
3+
//
4+
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5+
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6+
//
7+
// Official repository: https://github.com/cppalliance/http
8+
//
9+
10+
#ifndef BOOST_HTTP_SERVER_ESCAPE_HTML_HPP
11+
#define BOOST_HTTP_SERVER_ESCAPE_HTML_HPP
12+
13+
#include <boost/http/detail/config.hpp>
14+
#include <boost/core/detail/string_view.hpp>
15+
#include <string>
16+
17+
namespace boost {
18+
namespace http {
19+
20+
/** Escape a string for safe inclusion in HTML.
21+
22+
Replaces characters that have special meaning in HTML
23+
with their corresponding character entity references:
24+
25+
@li `&` becomes `&amp;`
26+
@li `<` becomes `&lt;`
27+
@li `>` becomes `&gt;`
28+
@li `"` becomes `&quot;`
29+
@li `'` becomes `&#39;`
30+
31+
This function is used to prevent XSS (Cross-Site Scripting)
32+
attacks when embedding user input in HTML responses.
33+
34+
@par Example
35+
@code
36+
std::string safe = escape_html( "<script>alert('xss')</script>" );
37+
// safe == "&lt;script&gt;alert(&#39;xss&#39;)&lt;/script&gt;"
38+
@endcode
39+
40+
@param s The string to escape.
41+
42+
@return A new string with HTML special characters escaped.
43+
*/
44+
BOOST_HTTP_DECL
45+
std::string
46+
escape_html(core::string_view s);
47+
48+
} // http
49+
} // boost
50+
51+
#endif

include/boost/http/server/etag.hpp

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
//
2+
// Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot com)
3+
//
4+
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5+
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6+
//
7+
// Official repository: https://github.com/cppalliance/http
8+
//
9+
10+
#ifndef BOOST_HTTP_SERVER_ETAG_HPP
11+
#define BOOST_HTTP_SERVER_ETAG_HPP
12+
13+
#include <boost/http/detail/config.hpp>
14+
#include <boost/core/detail/string_view.hpp>
15+
#include <cstdint>
16+
#include <string>
17+
18+
namespace boost {
19+
namespace http {
20+
21+
/** Options for ETag generation.
22+
*/
23+
struct etag_options
24+
{
25+
/// Generate a weak ETag (prefixed with W/).
26+
bool weak = false;
27+
};
28+
29+
/** Generate an ETag from content.
30+
31+
Creates an ETag by computing a hash of the provided
32+
content. The resulting ETag can be used in HTTP
33+
responses to enable caching.
34+
35+
@par Example
36+
@code
37+
std::string content = "Hello, World!";
38+
std::string tag = etag( content );
39+
// tag == "\"d-3/1gIbsr1bCvZ2KQgJ7DpTGR3YH\""
40+
@endcode
41+
42+
@param body The content to hash.
43+
44+
@param opts Options controlling ETag generation.
45+
46+
@return An ETag string suitable for use in the ETag header.
47+
*/
48+
BOOST_HTTP_DECL
49+
std::string
50+
etag(core::string_view body, etag_options opts = {});
51+
52+
/** Generate an ETag from file metadata.
53+
54+
Creates an ETag based on a file's size and modification
55+
time. This is more efficient than hashing file content
56+
and is suitable for static file serving.
57+
58+
@par Example
59+
@code
60+
std::uint64_t size = 1234;
61+
std::uint64_t mtime = 1704067200; // Unix timestamp
62+
std::string tag = etag( size, mtime );
63+
// tag == "\"4d2-65956a00\""
64+
@endcode
65+
66+
@param size The file size in bytes.
67+
68+
@param mtime The file modification time (typically Unix timestamp).
69+
70+
@param opts Options controlling ETag generation.
71+
72+
@return An ETag string suitable for use in the ETag header.
73+
*/
74+
BOOST_HTTP_DECL
75+
std::string
76+
etag(
77+
std::uint64_t size,
78+
std::uint64_t mtime,
79+
etag_options opts = {});
80+
81+
} // http
82+
} // boost
83+
84+
#endif

0 commit comments

Comments
 (0)