LCOV - code coverage report
Current view: top level - src/server - router_types.cpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 55.6 % 45 25 20
Test Date: 2026-06-13 19:44:58 Functions: 60.0 % 10 6 4

           TLA  Line data    Source code
       1                 : //
       2                 : // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.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                 : #include <boost/http/server/route_handler.hpp>
      11                 : #include <boost/http/server/etag.hpp>
      12                 : #include <boost/http/server/fresh.hpp>
      13                 : #include <boost/http/detail/except.hpp>
      14                 : #include <boost/url/grammar/ci_string.hpp>
      15                 : #include <boost/capy/buffers/make_buffer.hpp>
      16                 : #include <boost/assert.hpp>
      17                 : #include <cstring>
      18                 : 
      19                 : namespace boost {
      20                 : namespace system {
      21                 : template<>
      22                 : struct is_error_code_enum<
      23                 :     ::boost::http::route_what>
      24                 : {
      25                 :     static bool const value = true;
      26                 : };
      27                 : } // system
      28                 : } // boost
      29                 : 
      30                 : namespace boost {
      31                 : namespace http {
      32                 : 
      33                 : namespace {
      34                 : 
      35                 : struct route_what_cat_type
      36                 :     : system::error_category
      37                 : {
      38                 :     constexpr route_what_cat_type()
      39                 :         : error_category(0x7a8b3c4d5e6f1029)
      40                 :     {
      41                 :     }
      42                 : 
      43 MIS           0 :     const char* name() const noexcept override
      44                 :     {
      45               0 :         return "boost.http.route_what";
      46                 :     }
      47                 : 
      48               0 :     std::string message(int code) const override
      49                 :     {
      50               0 :         return message(code, nullptr, 0);
      51                 :     }
      52                 : 
      53               0 :     char const* message(
      54                 :         int code,
      55                 :         char*,
      56                 :         std::size_t) const noexcept override
      57                 :     {
      58               0 :         switch(static_cast<route_what>(code))
      59                 :         {
      60               0 :         case route_what::done:          return "done";
      61               0 :         case route_what::error:         return "error";
      62               0 :         case route_what::next:          return "next";
      63               0 :         case route_what::next_route:    return "next_route";
      64               0 :         case route_what::close:         return "close";
      65               0 :         default:
      66               0 :             return "?";
      67                 :         }
      68                 :     }
      69                 : };
      70                 : 
      71                 : route_what_cat_type route_what_cat;
      72                 : 
      73                 : } // (anon)
      74                 : 
      75                 : system::error_code
      76 HIT         166 : make_error_code(
      77                 :     route_what w) noexcept
      78                 : {
      79                 :     return system::error_code{
      80             166 :         static_cast<int>(w), route_what_cat};
      81                 : }
      82                 : 
      83                 : //----------------------------------------------------------
      84                 : 
      85              13 : route_result::
      86                 : route_result(
      87              13 :     system::error_code ec)
      88              13 :     : ec_(ec)
      89                 : {
      90              13 :     if(! ec.failed())
      91 MIS           0 :         detail::throw_invalid_argument();
      92 HIT          13 : }
      93                 : 
      94                 : void
      95             132 : route_result::
      96                 : set(route_what w)
      97                 : {
      98             132 :     ec_ = make_error_code(w);
      99             132 : }
     100                 : 
     101                 : auto
     102             456 : route_result::
     103                 : what() const noexcept ->
     104                 :     route_what
     105                 : {
     106             456 :     if(! ec_.failed())
     107             386 :         return route_what::done;    
     108              70 :     if(&ec_.category() != &route_what_cat)
     109              40 :         return route_what::error;
     110              30 :     if( ec_ == route_what::next)
     111              26 :         return route_what::next;
     112               4 :     if( ec_ == route_what::next_route)
     113               3 :         return route_what::next_route;
     114                 :     //if( ec_ == route_what::close)
     115               1 :     return route_what::close;
     116                 : }
     117                 : 
     118                 : auto
     119               9 : route_result::
     120                 : error() const noexcept ->
     121                 :     system::error_code
     122                 : {
     123               9 :     if(&ec_.category() != &route_what_cat)
     124               9 :         return ec_;
     125 MIS           0 :     return {};
     126                 : }
     127                 : 
     128                 : //------------------------------------------------
     129                 : 
     130                 : bool
     131               0 : route_params::
     132                 : is_method(
     133                 :     core::string_view s) const noexcept
     134                 : {
     135               0 :     auto m = http::string_to_method(s);
     136               0 :     if(m != http::method::unknown)
     137               0 :         return priv_.verb_ == m;
     138               0 :     return s == priv_.verb_str_;
     139                 : }
     140                 : 
     141                 : //------------------------------------------------
     142                 : 
     143                 : capy::io_task<>
     144 HIT           1 : route_params::
     145                 : send(std::string_view body)
     146                 : {
     147                 :     auto const sc = res.status();
     148                 : 
     149                 :     // 204 No Content / 304 Not Modified: strip headers, no body
     150                 :     if(sc == status::no_content ||
     151                 :        sc == status::not_modified)
     152                 :     {
     153                 :         res.erase(field::content_type);
     154                 :         res.erase(field::content_length);
     155                 :         res.erase(field::transfer_encoding);
     156                 :         co_return co_await res_body.write_eof();
     157                 :     }
     158                 : 
     159                 :     // 205 Reset Content: Content-Length=0, no body
     160                 :     if(sc == status::reset_content)
     161                 :     {
     162                 :         res.erase(field::transfer_encoding);
     163                 :         res.set_payload_size(0);
     164                 :         co_return co_await res_body.write_eof();
     165                 :     }
     166                 : 
     167                 :     // Set Content-Type if not already set
     168                 :     if(! res.exists(field::content_type))
     169                 :     {
     170                 :         if(! body.empty() && body[0] == '<')
     171                 :             res.set(field::content_type,
     172                 :                 "text/html; charset=utf-8");
     173                 :         else
     174                 :             res.set(field::content_type,
     175                 :                 "text/plain; charset=utf-8");
     176                 :     }
     177                 : 
     178                 :     // Generate ETag if not already set
     179                 :     if(! res.exists(field::etag))
     180                 :         res.set(field::etag, etag(body));
     181                 : 
     182                 :     // Set Content-Length if not already set
     183                 :     if(! res.exists(field::content_length))
     184                 :         res.set_payload_size(body.size());
     185                 : 
     186                 :     // Freshness check: auto-304 for conditional GET
     187                 :     if(is_fresh(req, res))
     188                 :     {
     189                 :         res.set_status(status::not_modified);
     190                 :         res.erase(field::content_type);
     191                 :         res.erase(field::content_length);
     192                 :         res.erase(field::transfer_encoding);
     193                 :         co_return co_await res_body.write_eof();
     194                 :     }
     195                 : 
     196                 :     // HEAD: send headers only, skip body
     197                 :     if(req.method() == method::head)
     198                 :     {
     199                 :         co_return co_await res_body.write_eof();
     200                 :     }
     201                 : 
     202                 :     auto [ec, n] = co_await res_body.write_eof(
     203                 :         capy::make_buffer(body));
     204                 :     co_return {ec};
     205               2 : }
     206                 : 
     207                 : } // http
     208                 : } // boost
        

Generated by: LCOV version 2.3