Skip to content
Closed
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
29 changes: 28 additions & 1 deletion example/server/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@
#include <boost/beast2/asio_io_context.hpp>
#include <boost/beast2/server/http_server.hpp>
#include <boost/beast2/server/router.hpp>
#include <boost/beast2/server/serve_not_found.hpp>
#include <boost/beast2/server/serve_static.hpp>
#include <boost/beast2/error.hpp>
#include <boost/capy/application.hpp>
#include <boost/http_proto/request_parser.hpp>
#include <boost/http_proto/serializer.hpp>
#include <boost/http_proto/server/cors.hpp>
#include <boost/http_proto/server/helmet.hpp>
#include <boost/capy/brotli/decode.hpp>
#include <boost/capy/brotli/encode.hpp>
#include <boost/capy/zlib/deflate.hpp>
Expand Down Expand Up @@ -187,7 +189,32 @@ int server_main( int argc, char* argv[] )
}
return http::route::next;
});
srv.wwwroot.use("/", serve_static( argv[3] ));

http::helmet_options options;

options.set(http::x_download_options(http::helmet_download_type::noopen));
options.set(http::x_frame_origin(http::helmet_origin_type::deny));

http::helmet::csp_policy sp;

sp.allow("script-src", http::csp_type::self)
.allow("object-src", http::csp_type::none)
.allow("style-src", "https://example.com/index.css")
.allow("style-src", "https://example.com/foo.css")
.allow("style-src", http::csp_type::self);

options.set(http::content_security_policy(sp));

srv.wwwroot.use(
http::helmet(options),
[] ( http::route_params& ) ->
http::route_result
{
return http::route::next;
});

srv.wwwroot.use("/", serve_not_found( argv[3] ));
srv.wwwroot.use("/", serve_static( argv[3] ));

app.start();
srv.attach();
Expand Down
44 changes: 44 additions & 0 deletions include/boost/beast2/server/serve_not_found.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// Copyright (c) 2025 Amlal El Mahrouss (amlal at nekernel dot org)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/cppalliance/beast2
//

#ifndef BOOST_BEAST2_SERVER_SERVE_REDIRECT_HPP
#define BOOST_BEAST2_SERVER_SERVE_REDIRECT_HPP

#include <boost/beast2/detail/config.hpp>
#include <boost/http_proto/server/route_handler.hpp>

namespace boost {
namespace beast2 {

struct serve_not_found
{
private:
struct serve_impl;
serve_impl* impl_{};

public:
serve_not_found(const core::string_view&);
~serve_not_found();

serve_not_found& operator=(serve_not_found&&) noexcept;
serve_not_found(serve_not_found&&) noexcept;

/** Serves a 404.html when a resource isn't found.
@note if no 404.html is found the route will be ignored.
*/
BOOST_BEAST2_DECL
http::route_result
operator()(
http::route_params&) const;
};

} // beast2
} // boost

#endif
99 changes: 99 additions & 0 deletions src/server/serve_not_found.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
//
// Copyright (c) 2025 Amlal El Mahrouss (amlal at nekernel dot org)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/cppalliance/beast2
//

#include <boost/beast2/server/serve_not_found.hpp>
#include <boost/capy/file.hpp>
#include <boost/http_proto/file_source.hpp>
#include <boost/http_proto/status.hpp>
#include <boost/http_proto/string_body.hpp>
#include <sstream>

namespace boost {
namespace beast2 {

struct serve_not_found::serve_impl
{
std::string path_;
};

serve_not_found::serve_not_found(const core::string_view& path)
: impl_(new serve_impl())
{
impl_->path_ = path;
}

serve_not_found::~serve_not_found()
{
if (impl_)
delete impl_;

impl_ = nullptr;
}

serve_not_found& serve_not_found::operator=(serve_not_found&& other) noexcept
{
delete impl_;
impl_ = other.impl_;
other.impl_ = nullptr;

return *this;
}

serve_not_found::
serve_not_found(serve_not_found&& other) noexcept
: impl_(other.impl_)
{
other.impl_ = nullptr;
}

http::route_result
serve_not_found::operator()(
http::route_params& p) const
{
std::string path{impl_->path_};
path += p.path;

system::error_code ec{};

capy::file f;

f.open(path.c_str(), capy::file_mode::scan, ec);

if (!ec.failed())
return http::route::next;

p.res.set_start_line(http::status::not_found);
p.res.append(http::field::content_type, "text/html");

std::string body;
std::ostringstream ss;

ss <<
"<HTML>"
"<HEAD>"
"<TITLE>NOT FOUND</TITLE>"
"</HEAD>\n"
"<BODY>"
"<H1>NOT FOUND</H1>"
"<P>THE FOLLOWING RESOURCE: " << p.path << ", WAS NOT FOUND.</P>"
"</BODY>"
"</HTML>"
;

body = ss.str();

// send 404 template to client
p.serializer.start(p.res,
http::string_body( std::move(body)));

return http::route::send;
}

}
}