LCOV - code coverage report
Current view: top level - boost/http_proto - response.hpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 98.3 % 59 58
Test Date: 2025-12-18 06:34:36 Functions: 100.0 % 17 17

            Line data    Source code
       1              : //
       2              : // Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com)
       3              : // Copyright (c) 2024 Christian Mazakas
       4              : // Copyright (c) 2025 Mohammad Nejati
       5              : //
       6              : // Distributed under the Boost Software License, Version 1.0. (See accompanying
       7              : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
       8              : //
       9              : // Official repository: https://github.com/cppalliance/http_proto
      10              : //
      11              : 
      12              : #ifndef BOOST_HTTP_PROTO_RESPONSE_HPP
      13              : #define BOOST_HTTP_PROTO_RESPONSE_HPP
      14              : 
      15              : #include <boost/http_proto/detail/config.hpp>
      16              : #include <boost/http_proto/message_base.hpp>
      17              : #include <boost/http_proto/status.hpp>
      18              : 
      19              : namespace boost {
      20              : namespace http_proto {
      21              : 
      22              : /** A container for HTTP responses.
      23              : 
      24              :     This container owns a response, represented by
      25              :     a buffer which is managed by performing
      26              :     dynamic memory allocations as needed. The
      27              :     contents may be inspected and modified, and
      28              :     the implementation maintains a useful
      29              :     invariant: changes to the response always
      30              :     leave it in a valid state.
      31              : 
      32              :     @par Example
      33              :     @code
      34              :     response res(status::not_found);
      35              : 
      36              :     res.set(field::server, "Boost.HttpProto");
      37              :     res.set(field::content_type, "text/plain");
      38              :     res.set_content_length(80);
      39              : 
      40              :     assert(res.buffer() ==
      41              :         "HTTP/1.1 404 Not Found\r\n"
      42              :         "Server: Boost.HttpProto\r\n"
      43              :         "Content-Type: text/plain\r\n"
      44              :         "Content-Length: 80\r\n"
      45              :         "\r\n");
      46              :     @endcode
      47              : 
      48              :     @see
      49              :         @ref response_parser,
      50              :         @ref request.
      51              : */
      52              : class response
      53              :     : public message_base
      54              : {
      55              :     friend class response_parser;
      56              : 
      57            1 :     response(
      58              :         view_tag_t,
      59              :         detail::header const& h) noexcept
      60            1 :         : message_base(view_tag, h)
      61              :     {
      62            1 :     }
      63              : 
      64              : public:
      65              :     //--------------------------------------------
      66              :     //
      67              :     // Special Members
      68              :     //
      69              :     //--------------------------------------------
      70              : 
      71              :     /** Constructor.
      72              : 
      73              :         A default-constructed response contains
      74              :         a valid HTTP 200 OK response with no headers.
      75              : 
      76              :         @par Example
      77              :         @code
      78              :         response res;
      79              :         @endcode
      80              : 
      81              :         @par Postconditions
      82              :         @code
      83              :         this->buffer() == "HTTP/1.1 200 OK\r\n\r\n"
      84              :         @endcode
      85              : 
      86              :         @par Complexity
      87              :         Constant.
      88              :     */
      89           99 :     response() noexcept
      90           99 :         : message_base(detail::kind::response)
      91              :     {
      92           99 :     }
      93              : 
      94              :     /** Constructor.
      95              : 
      96              :         Constructs a response from the string `s`,
      97              :         which must contain valid HTTP response
      98              :         or else an exception is thrown.
      99              :         The new response retains ownership by
     100              :         making a copy of the passed string.
     101              : 
     102              :         @par Example
     103              :         @code
     104              :         response res(
     105              :             "HTTP/1.1 404 Not Found\r\n"
     106              :             "Server: Boost.HttpProto\r\n"
     107              :             "Content-Type: text/plain\r\n"
     108              :             "\r\n");
     109              :         @endcode
     110              : 
     111              :         @par Postconditions
     112              :         @code
     113              :         this->buffer.data() != s.data()
     114              :         @endcode
     115              : 
     116              :         @par Complexity
     117              :         Linear in `s.size()`.
     118              : 
     119              :         @par Exception Safety
     120              :         Calls to allocate may throw.
     121              :         Exception thrown on invalid input.
     122              : 
     123              :         @throw system_error
     124              :         The input does not contain a valid response.
     125              : 
     126              :         @param s The string to parse.
     127              :     */
     128              :     explicit
     129           99 :     response(
     130              :         core::string_view s)
     131           99 :         : message_base(detail::kind::response, s)
     132              :     {
     133           98 :     }
     134              : 
     135              :     /** Constructor.
     136              : 
     137              :         Allocates `cap` bytes initially, with an
     138              :         upper limit of `max_cap`. Growing beyond
     139              :         `max_cap` will throw an exception.
     140              : 
     141              :         Useful when an estimated initial size is
     142              :         known, but further growth up to a maximum
     143              :         is allowed.
     144              : 
     145              :         When `max_cap == cap`, the container
     146              :         guarantees to never allocate.
     147              : 
     148              :         @par Preconditions
     149              :         @code
     150              :         max_cap >= cap
     151              :         @endcode
     152              : 
     153              :         @par Exception Safety
     154              :         Calls to allocate may throw.
     155              : 
     156              :         @param cap Initial capacity in bytes (may be `0`).
     157              : 
     158              :         @param max_cap Maximum allowed capacity in bytes.
     159              :     */
     160              :     explicit
     161           10 :     response(
     162              :         std::size_t cap,
     163              :         std::size_t max_cap = std::size_t(-1))
     164           10 :         : response()
     165              :     {
     166           10 :         reserve_bytes(cap);
     167           10 :         set_max_capacity_in_bytes(max_cap);
     168           10 :     }
     169              : 
     170              :     /** Constructor.
     171              : 
     172              :         The start-line of the response will
     173              :         contain the standard text for the
     174              :         supplied status code and HTTP version.
     175              : 
     176              :         @par Example
     177              :         @code
     178              :         response res(status::not_found, version::http_1_0);
     179              :         @endcode
     180              : 
     181              :         @par Complexity
     182              :         Linear in `to_string(s).size()`.
     183              : 
     184              :         @par Exception Safety
     185              :         Calls to allocate may throw.
     186              : 
     187              :         @param sc The status code.
     188              : 
     189              :         @param v The HTTP version.
     190              :     */
     191            9 :     response(
     192              :         http_proto::status sc,
     193              :         http_proto::version v)
     194            9 :         : response()
     195              :     {
     196            9 :         set_start_line(sc, v);
     197            9 :     }
     198              : 
     199              :     /** Constructor.
     200              : 
     201              :         The start-line of the response will
     202              :         contain the standard text for the
     203              :         supplied status code with the HTTP version
     204              :         defaulted to `HTTP/1.1`.
     205              : 
     206              :         @par Example
     207              :         @code
     208              :         response res(status::not_found);
     209              :         @endcode
     210              : 
     211              :         @par Complexity
     212              :         Linear in `to_string(s).size()`.
     213              : 
     214              :         @par Exception Safety
     215              :         Calls to allocate may throw.
     216              : 
     217              :         @param sc The status code.
     218              :     */
     219              :     explicit
     220            2 :     response(
     221              :         http_proto::status sc)
     222            2 :         : response(
     223            2 :             sc, http_proto::version::http_1_1)
     224              :     {
     225            2 :     }
     226              : 
     227              :     /** Constructor.
     228              : 
     229              :         The contents of `r` are transferred
     230              :         to the newly constructed object,
     231              :         which includes the underlying
     232              :         character buffer.
     233              :         After construction, the moved-from
     234              :         object is as if default-constructed.
     235              : 
     236              :         @par Postconditions
     237              :         @code
     238              :         r.buffer() == "HTTP/1.1 200 OK\r\n\r\n"
     239              :         @endcode
     240              : 
     241              :         @par Complexity
     242              :         Constant.
     243              : 
     244              :         @param r The response to move from.
     245              :     */
     246            3 :     response(response&& r) noexcept
     247            3 :         : response()
     248              :     {
     249            3 :         swap(r);
     250            3 :     }
     251              : 
     252              :     /** Constructor.
     253              : 
     254              :         The newly constructed object contains
     255              :         a copy of `r`.
     256              : 
     257              :         @par Postconditions
     258              :         @code
     259              :         this->buffer() == r.buffer() && this->buffer.data() != r.buffer().data()
     260              :         @endcode
     261              : 
     262              :         @par Complexity
     263              :         Linear in `r.size()`.
     264              : 
     265              :         @par Exception Safety
     266              :         Calls to allocate may throw.
     267              : 
     268              :         @param r The response to copy.
     269              :     */
     270            3 :     response(response const&) = default;
     271              : 
     272              :     /** Assignment
     273              : 
     274              :         The contents of `r` are transferred to
     275              :         `this`, including the underlying
     276              :         character buffer. The previous contents
     277              :         of `this` are destroyed.
     278              :         After assignment, the moved-from
     279              :         object is as if default-constructed.
     280              : 
     281              :         @par Postconditions
     282              :         @code
     283              :         r.buffer() == "HTTP/1.1 200 OK\r\n\r\n"
     284              :         @endcode
     285              : 
     286              :         @par Complexity
     287              :         Constant.
     288              : 
     289              :         @param r The response to assign from.
     290              : 
     291              :         @return A reference to this object.
     292              :     */
     293              :     response&
     294            1 :     operator=(
     295              :         response&& r) noexcept
     296              :     {
     297            1 :         response temp(std::move(r));
     298            1 :         temp.swap(*this);
     299            2 :         return *this;
     300            1 :     }
     301              : 
     302              :     /** Assignment.
     303              : 
     304              :         The contents of `r` are copied and
     305              :         the previous contents of `this` are
     306              :         discarded.
     307              : 
     308              :         @par Postconditions
     309              :         @code
     310              :         this->buffer() == r.buffer() && this->buffer().data() != r.buffer().data()
     311              :         @endcode
     312              : 
     313              :         @par Complexity
     314              :         Linear in `r.size()`.
     315              : 
     316              :         @par Exception Safety
     317              :         Strong guarantee.
     318              :         Calls to allocate may throw.
     319              :         Exception thrown if max capacity exceeded.
     320              : 
     321              :         @throw std::length_error
     322              :         Max capacity would be exceeded.
     323              : 
     324              :         @param r The response to copy.
     325              : 
     326              :         @return A reference to this object.
     327              :     */
     328              :     response&
     329            1 :     operator=(
     330              :         response const& r)
     331              :     {
     332            1 :         copy_impl(r.h_);
     333            1 :         return *this;
     334              :     }
     335              : 
     336              :     //--------------------------------------------
     337              : 
     338              :     /** Swap.
     339              : 
     340              :         Exchanges the contents of this response
     341              :         with another response. All views,
     342              :         iterators and references remain valid.
     343              : 
     344              :         If `this == &other`, this function call has no effect.
     345              : 
     346              :         @par Example
     347              :         @code
     348              :         response r1(status::ok);
     349              :         response r2(status::bad_request);
     350              :         r1.swap(r2);
     351              :         assert(r1.buffer() == "HTTP/1.1 400 Bad Request\r\n\r\n" );
     352              :         assert(r2.buffer() == "HTTP/1.1 200 OK\r\n\r\n" );
     353              :         @endcode
     354              : 
     355              :         @par Complexity
     356              :         Constant
     357              : 
     358              :         @param other The object to swap with
     359              :     */
     360              :     void
     361            4 :     swap(response& other) noexcept
     362              :     {
     363            4 :         h_.swap(other.h_);
     364            4 :         std::swap(max_cap_, other.max_cap_);
     365            4 :         std::swap(view_, other.view_);
     366            4 :     }
     367              : 
     368              :     /** Swap.
     369              : 
     370              :         Exchanges the contents of `v0` with
     371              :         another `v1`. All views, iterators and
     372              :         references remain valid.
     373              : 
     374              :         If `&v0 == &v1`, this function call has no effect.
     375              : 
     376              :         @par Example
     377              :         @code
     378              :         response r1(status::ok);
     379              :         response r2(status::bad_request);
     380              :         std::swap(r1, r2);
     381              :         assert(r1.buffer() == "HTTP/1.1 400 Bad Request\r\n\r\n" );
     382              :         assert(r2.buffer() == "HTTP/1.1 200 OK\r\n\r\n" );
     383              :         @endcode
     384              : 
     385              :         @par Effects
     386              :         @code
     387              :         v0.swap(v1);
     388              :         @endcode
     389              : 
     390              :         @par Complexity
     391              :         Constant.
     392              : 
     393              :         @param v0 The first object to swap.
     394              :         @param v1 The second object to swap.
     395              : 
     396              :         @see
     397              :             @ref response::swap.
     398              :     */
     399              :     friend
     400              :     void
     401              :     swap(
     402              :         response& v0,
     403              :         response& v1) noexcept
     404              :     {
     405              :         v0.swap(v1);
     406              :     }
     407              : 
     408              :     //--------------------------------------------
     409              :     //
     410              :     // Observers
     411              :     //
     412              :     //--------------------------------------------
     413              : 
     414              :     /** Return the reason string.
     415              : 
     416              :         This field is obsolete in HTTP/1
     417              :         and should only be used for display
     418              :         purposes.
     419              :     */
     420              :     core::string_view
     421           26 :     reason() const noexcept
     422              :     {
     423           52 :         return core::string_view(
     424           26 :             h_.cbuf + 13,
     425           26 :             h_.prefix - 15);
     426              :     }
     427              : 
     428              :     /** Return the status code.
     429              :     */
     430              :     http_proto::status
     431           26 :     status() const noexcept
     432              :     {
     433           26 :         return h_.res.status;
     434              :     }
     435              : 
     436              :     /** Return the status code as an integral.
     437              :     */
     438              :     unsigned short
     439           26 :     status_int() const noexcept
     440              :     {
     441           26 :         return h_.res.status_int;
     442              :     }
     443              : 
     444              :     //--------------------------------------------
     445              :     //
     446              :     // Modifiers
     447              :     //
     448              :     //--------------------------------------------
     449              : 
     450              :     /** Set the status code and version of the response.
     451              : 
     452              :         The reason-phrase will be set to the
     453              :         standard text for the specified status
     454              :         code.
     455              : 
     456              :         This is more efficient than setting the
     457              :         properties individually.
     458              : 
     459              :         @par Exception Safety
     460              :         Strong guarantee.
     461              :         Calls to allocate may throw.
     462              :         Exception thrown if max capacity exceeded.
     463              : 
     464              :         @throw std::length_error
     465              :         Max capacity would be exceeded.
     466              :         @throw std::invalid_argument
     467              :         `sc == status::unknown`
     468              : 
     469              :         @param sc The status code to set. This
     470              :         must not be @ref status::unknown.
     471              : 
     472              :         @param v The version to set.
     473              :     */
     474              :     void
     475           11 :     set_start_line(
     476              :         http_proto::status sc,
     477              :         http_proto::version v =
     478              :             http_proto::version::http_1_1)
     479              :     {
     480           11 :         set_start_line_impl(sc,
     481              :             static_cast<unsigned short>(sc),
     482              :                 to_string(sc), v);
     483           11 :     }
     484              : 
     485              :     /** Set the HTTP version of the response
     486              : 
     487              :         @par Exception Safety
     488              :         Strong guarantee.
     489              :         Calls to allocate may throw.
     490              :         Exception thrown if maximum capacity exceeded.
     491              : 
     492              :         @throw std::length_error
     493              :         Maximum capacity would be exceeded.
     494              : 
     495              :         @param v The version to set.
     496              :     */
     497              :     BOOST_HTTP_PROTO_DECL
     498              :     void
     499              :     set_version(
     500              :         http_proto::version v);
     501              : 
     502              :     /** Set the status code of the response.
     503              : 
     504              :         The reason-phrase will be set to the
     505              :         standard text for the specified status
     506              :         code. The version will remain unchanged.
     507              : 
     508              :         @par Exception Safety
     509              :         Strong guarantee.
     510              :         Calls to allocate may throw.
     511              :         Exception thrown if maximum capacity exceeded.
     512              : 
     513              :         @throw std::length_error
     514              :         Maximum capacity would be exceeded.
     515              :         @throw std::invalid_argument
     516              :         `sc == status::unknown`
     517              : 
     518              :         @param sc The status code to set. This
     519              :         must not be @ref status::unknown.
     520              :     */
     521              :     void
     522            3 :     set_status(
     523              :         http_proto::status sc)
     524              :     {
     525            3 :         if(sc == http_proto::status::unknown)
     526            0 :             detail::throw_invalid_argument();
     527            3 :         set_start_line_impl(sc,
     528              :             static_cast<unsigned short>(sc),
     529              :             to_string(sc),
     530              :             version());
     531            3 :     }
     532              : 
     533              :     /** Set the status code and version of the response.
     534              : 
     535              :         The reason-phrase will be set to the
     536              :         standard text for the specified status
     537              :         code.
     538              : 
     539              :         This is more efficient than setting the
     540              :         properties individually.
     541              : 
     542              :         @par Exception Safety
     543              :         Strong guarantee.
     544              :         Calls to allocate may throw.
     545              :         Exception thrown on invalid input.
     546              :         Exception thrown if max capacity exceeded.
     547              : 
     548              :         @throw system_error
     549              :         Input is invalid.
     550              : 
     551              :         @throw std::length_error
     552              :         Max capacity would be exceeded.
     553              : 
     554              :         @param si An integral representing the
     555              :         status code to set.
     556              : 
     557              :         @param reason A string view representing the
     558              :         reason string to set.
     559              : 
     560              :         @param v The version to set.
     561              :     */
     562              :     void
     563            8 :     set_start_line(
     564              :         unsigned short si,
     565              :         core::string_view reason,
     566              :         http_proto::version v =
     567              :             http_proto::version::http_1_1)
     568              :     {
     569            8 :         set_start_line_impl(
     570              :             int_to_status(si),
     571              :             si,
     572              :             reason,
     573              :             v);
     574            7 :     }
     575              : 
     576              : private:
     577              :     BOOST_HTTP_PROTO_DECL
     578              :     void
     579              :     set_start_line_impl(
     580              :         http_proto::status sc,
     581              :         unsigned short si,
     582              :         core::string_view reason,
     583              :         http_proto::version v);
     584              : };
     585              : 
     586              : } // http_proto
     587              : } // boost
     588              : 
     589              : #endif
        

Generated by: LCOV version 2.1