LCOV - code coverage report
Current view: top level - libs/beast2/src/server/serve_static.cpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 0.0 % 91 0
Test Date: 2025-11-13 15:50:43 Functions: 0.0 % 8 0

            Line data    Source code
       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/beast2
       8              : //
       9              : 
      10              : #include <boost/beast2/server/serve_static.hpp>
      11              : #include <boost/beast2/error.hpp>
      12              : #include <boost/http_proto/file_source.hpp>
      13              : #include <boost/url/grammar/ci_string.hpp>
      14              : #include <string>
      15              : 
      16              : namespace boost {
      17              : namespace beast2 {
      18              : 
      19              : //------------------------------------------------
      20              : 
      21              : // Return a reasonable mime type based on the extension of a file.
      22              : static
      23              : core::string_view
      24            0 : get_extension(
      25              :     core::string_view path) noexcept
      26              : {
      27            0 :     auto const pos = path.rfind(".");
      28            0 :     if( pos == core::string_view::npos)
      29            0 :         return core::string_view();
      30            0 :     return path.substr(pos);
      31              : }
      32              : 
      33              : static
      34              : core::string_view
      35            0 : mime_type(
      36              :     core::string_view path)
      37              : {
      38              :     using urls::grammar::ci_is_equal;
      39            0 :     auto ext = get_extension(path);
      40            0 :     if(ci_is_equal(ext, ".htm"))  return "text/html";
      41            0 :     if(ci_is_equal(ext, ".html")) return "text/html";
      42            0 :     if(ci_is_equal(ext, ".php"))  return "text/html";
      43            0 :     if(ci_is_equal(ext, ".css"))  return "text/css";
      44            0 :     if(ci_is_equal(ext, ".txt"))  return "text/plain";
      45            0 :     if(ci_is_equal(ext, ".js"))   return "application/javascript";
      46            0 :     if(ci_is_equal(ext, ".json")) return "application/json";
      47            0 :     if(ci_is_equal(ext, ".xml"))  return "application/xml";
      48            0 :     if(ci_is_equal(ext, ".swf"))  return "application/x-shockwave-flash";
      49            0 :     if(ci_is_equal(ext, ".flv"))  return "video/x-flv";
      50            0 :     if(ci_is_equal(ext, ".png"))  return "image/png";
      51            0 :     if(ci_is_equal(ext, ".jpe"))  return "image/jpeg";
      52            0 :     if(ci_is_equal(ext, ".jpeg")) return "image/jpeg";
      53            0 :     if(ci_is_equal(ext, ".jpg"))  return "image/jpeg";
      54            0 :     if(ci_is_equal(ext, ".gif"))  return "image/gif";
      55            0 :     if(ci_is_equal(ext, ".bmp"))  return "image/bmp";
      56            0 :     if(ci_is_equal(ext, ".ico"))  return "image/vnd.microsoft.icon";
      57            0 :     if(ci_is_equal(ext, ".tiff")) return "image/tiff";
      58            0 :     if(ci_is_equal(ext, ".tif"))  return "image/tiff";
      59            0 :     if(ci_is_equal(ext, ".svg"))  return "image/svg+xml";
      60            0 :     if(ci_is_equal(ext, ".svgz")) return "image/svg+xml";
      61            0 :     return "application/text";
      62              : }
      63              : 
      64              : #if 0
      65              : // Append an HTTP rel-path to a local filesystem path.
      66              : // The returned path is normalized for the platform.
      67              : static
      68              : void
      69              : path_cat(
      70              :     std::string& result,
      71              :     core::string_view prefix,
      72              :     urls::segments_view suffix)
      73              : {
      74              :     result = prefix;
      75              : 
      76              : #ifdef BOOST_MSVC
      77              :     char constexpr path_separator = '\\';
      78              : #else
      79              :     char constexpr path_separator = '/';
      80              : #endif
      81              :     if( result.back() == path_separator)
      82              :         result.resize(result.size() - 1); // remove trailing
      83              : #ifdef BOOST_MSVC
      84              :     for(auto& c : result)
      85              :         if( c == '/')
      86              :             c = path_separator;
      87              : #endif
      88              :     for(auto const& seg : suffix)
      89              :     {
      90              :         result.push_back(path_separator);
      91              :         result.append(seg);
      92              :     }
      93              : }
      94              : #endif
      95              : 
      96              : // Append an HTTP rel-path to a local filesystem path.
      97              : // The returned path is normalized for the platform.
      98              : static
      99              : void
     100            0 : path_cat(
     101              :     std::string& result,
     102              :     core::string_view prefix,
     103              :     core::string_view suffix)
     104              : {
     105            0 :     result = prefix;
     106              : 
     107              : #ifdef BOOST_MSVC
     108              :     char constexpr path_separator = '\\';
     109              : #else
     110            0 :     char constexpr path_separator = '/';
     111              : #endif
     112            0 :     if( result.back() == path_separator)
     113            0 :         result.resize(result.size() - 1); // remove trailing
     114              : #ifdef BOOST_MSVC
     115              :     for(auto& c : result)
     116              :         if( c == '/')
     117              :             c = path_separator;
     118              : #endif
     119            0 :     for(auto const& c : suffix)
     120              :     {
     121            0 :         if(c == '/')
     122            0 :             result.push_back(path_separator);
     123              :         else 
     124            0 :             result.push_back(c);
     125              :     }
     126            0 : }
     127              : 
     128              : //------------------------------------------------
     129              : 
     130              : // serve-static
     131              : //
     132              : // https://www.npmjs.com/package/serve-static
     133              : 
     134              : struct serve_static::impl
     135              : {
     136            0 :     impl(
     137              :         core::string_view path_,
     138              :         options const& opt_)
     139            0 :         : path(path_)
     140            0 :         , opt(opt_)
     141              :     {
     142            0 :     }
     143              : 
     144              :     std::string path;
     145              :     options opt;
     146              : };
     147              : 
     148            0 : serve_static::
     149              : ~serve_static()
     150              : {
     151            0 :     if(impl_)
     152            0 :         delete impl_;
     153            0 : }
     154              : 
     155            0 : serve_static::
     156            0 : serve_static(serve_static&& other) noexcept
     157            0 :     : impl_(other.impl_)
     158              : {
     159            0 :     other.impl_ = nullptr;
     160            0 : }
     161              : 
     162            0 : serve_static::
     163              : serve_static(
     164              :     core::string_view path,
     165            0 :     options const& opt)
     166            0 :     : impl_(new impl(path, opt))
     167              : {
     168            0 : }
     169              : 
     170              : auto
     171            0 : serve_static::
     172              : operator()(
     173              :     Request& req,
     174              :     Response& res) const ->
     175              :         route_result
     176              : {
     177              :     // Allow: GET, HEAD
     178            0 :     if( req.m.method() != http_proto::method::get &&
     179            0 :         req.m.method() != http_proto::method::head)
     180              :     {
     181            0 :         if(impl_->opt.fallthrough)
     182            0 :             return route::next;
     183              : 
     184            0 :         res.m.set_status(
     185              :             http_proto::status::method_not_allowed);
     186            0 :         res.m.set(http_proto::field::allow, "GET, HEAD");
     187            0 :         res.set_body("");
     188            0 :         return route::send;
     189              :     }
     190              : 
     191              :     // Build the path to the requested file
     192            0 :     std::string path;
     193            0 :     path_cat(path, impl_->path, req.path);
     194            0 :     if(req.pr.get().target().back() == '/')
     195              :     {
     196            0 :         path.push_back('/');
     197            0 :         path.append("index.html");
     198              :     }
     199              : 
     200              :     // Attempt to open the file
     201            0 :     system::error_code ec;
     202            0 :     http_proto::file f;
     203            0 :     std::uint64_t size = 0;
     204            0 :     f.open(path.c_str(), http_proto::file_mode::scan, ec);
     205            0 :     if(! ec.failed())
     206            0 :         size = f.size(ec);
     207            0 :     if(! ec.failed())
     208              :     {
     209            0 :         res.m.set_start_line(
     210              :             http_proto::status::ok,
     211            0 :             req.m.version());
     212            0 :         res.m.set_payload_size(size);
     213              : 
     214            0 :         auto mt = mime_type(get_extension(path));
     215            0 :         res.m.append(
     216              :             http_proto::field::content_type, mt);
     217              : 
     218              :         // send file
     219            0 :         res.sr.start<http_proto::file_source>(
     220            0 :             res.m, std::move(f), size);
     221            0 :         return route::send;
     222              :     }
     223              : 
     224            0 :     if( ec == system::errc::no_such_file_or_directory &&
     225            0 :         ! impl_->opt.fallthrough)
     226            0 :         return route::next;
     227              : 
     228            0 :     BOOST_ASSERT(ec.failed());
     229            0 :     return ec;
     230            0 : }
     231              : 
     232              : } // beast2
     233              : } // boost
     234              : 
        

Generated by: LCOV version 2.1