1 //
2 // Copyright (c) 2016-2019 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/boostorg/beast
8 //
9 
10 #ifndef BOOST_BEAST_HTTP_TEST_PARSER_HPP
11 #define BOOST_BEAST_HTTP_TEST_PARSER_HPP
12 
13 #include <boost/beast/http/basic_parser.hpp>
14 #include <boost/beast/_experimental/test/fail_count.hpp>
15 #include <string>
16 #include <unordered_map>
17 
18 namespace boost {
19 namespace beast {
20 namespace http {
21 
22 template<bool isRequest>
23 class test_parser
24     : public basic_parser<isRequest>
25 {
26     test::fail_count* fc_ = nullptr;
27 
28 public:
29     using mutable_buffers_type =
30         net::mutable_buffer;
31 
32     int status = 0;
33     int version = 0;
34     std::string method;
35     std::string path;
36     std::string reason;
37     std::string body;
38     int got_on_begin       = 0;
39     int got_on_field       = 0;
40     int got_on_header      = 0;
41     int got_on_body        = 0;
42     int got_content_length = 0;
43     int got_on_chunk       = 0;
44     int got_on_complete    = 0;
45     std::unordered_map<
46         std::string, std::string> fields;
47 
48     test_parser() = default;
49 
50     explicit
test_parser(test::fail_count & fc)51     test_parser(test::fail_count& fc)
52         : fc_(&fc)
53     {
54     }
55 
56     void
on_request_impl(verb,string_view method_str_,string_view path_,int version_,error_code & ec)57     on_request_impl(verb, string_view method_str_,
58         string_view path_, int version_, error_code& ec)
59     {
60         method = std::string(
61             method_str_.data(), method_str_.size());
62         path = std::string(
63             path_.data(), path_.size());
64         version = version_;
65         ++got_on_begin;
66         if(fc_)
67             fc_->fail(ec);
68     }
69 
70     void
on_response_impl(int code,string_view reason_,int version_,error_code & ec)71     on_response_impl(int code,
72         string_view reason_,
73             int version_, error_code& ec)
74     {
75         status = code;
76         reason = std::string(
77             reason_.data(), reason_.size());
78         version = version_;
79         ++got_on_begin;
80         if(fc_)
81             fc_->fail(ec);
82     }
83 
84     void
on_field_impl(field,string_view name,string_view value,error_code & ec)85     on_field_impl(field, string_view name,
86         string_view value, error_code& ec)
87     {
88         ++got_on_field;
89         if(fc_)
90             fc_->fail(ec);
91         fields[std::string(name)] = std::string(value);
92     }
93 
94     void
on_header_impl(error_code & ec)95     on_header_impl(error_code& ec)
96     {
97         ++got_on_header;
98         if(fc_)
99             fc_->fail(ec);
100     }
101 
102     void
on_body_init_impl(boost::optional<std::uint64_t> const & content_length_,error_code & ec)103     on_body_init_impl(
104         boost::optional<std::uint64_t> const& content_length_,
105         error_code& ec)
106     {
107         ++got_on_body;
108         got_content_length =
109             static_cast<bool>(content_length_);
110         if(fc_)
111             fc_->fail(ec);
112     }
113 
114     std::size_t
on_body_impl(string_view s,error_code & ec)115     on_body_impl(string_view s,
116         error_code& ec)
117     {
118         body.append(s.data(), s.size());
119         if(fc_)
120             fc_->fail(ec);
121         return s.size();
122     }
123 
124     void
on_chunk_header_impl(std::uint64_t,string_view,error_code & ec)125     on_chunk_header_impl(
126         std::uint64_t,
127         string_view,
128         error_code& ec)
129     {
130         ++got_on_chunk;
131         if(fc_)
132             fc_->fail(ec);
133     }
134 
135     std::size_t
on_chunk_body_impl(std::uint64_t,string_view s,error_code & ec)136     on_chunk_body_impl(
137         std::uint64_t,
138         string_view s,
139         error_code& ec)
140     {
141         body.append(s.data(), s.size());
142         if(fc_)
143             fc_->fail(ec);
144         return s.size();
145     }
146 
147 
148     void
on_finish_impl(error_code & ec)149     on_finish_impl(error_code& ec)
150     {
151         ++got_on_complete;
152         if(fc_)
153             fc_->fail(ec);
154     }
155 };
156 
157 } // http
158 } // beast
159 } // boost
160 
161 #endif
162