]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // |
2 | // Copyright (c) 2013-2017 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 | ||
8 | // Test that header file is self-contained. | |
9 | #include <beast/http/message_parser.hpp> | |
10 | ||
11 | #include "test_parser.hpp" | |
12 | ||
13 | #include <beast/unit_test/suite.hpp> | |
14 | #include <beast/test/string_istream.hpp> | |
15 | #include <beast/test/string_ostream.hpp> | |
16 | #include <beast/test/yield_to.hpp> | |
17 | #include <beast/core/flat_streambuf.hpp> | |
18 | #include <beast/core/streambuf.hpp> | |
19 | #include <beast/http/header_parser.hpp> | |
20 | #include <beast/http/read.hpp> | |
21 | #include <beast/http/read.hpp> | |
22 | #include <beast/http/string_body.hpp> | |
23 | #include <boost/system/system_error.hpp> | |
24 | ||
25 | namespace beast { | |
26 | namespace http { | |
27 | ||
28 | class message_parser_test | |
29 | : public beast::unit_test::suite | |
30 | , public beast::test::enable_yield_to | |
31 | { | |
32 | public: | |
33 | template<bool isRequest, class Pred> | |
34 | void | |
35 | testMatrix(std::string const& s, Pred const& pred) | |
36 | { | |
37 | beast::test::string_istream ss{get_io_service(), s}; | |
38 | error_code ec; | |
39 | #if 0 | |
40 | streambuf dynabuf; | |
41 | #else | |
42 | flat_streambuf dynabuf{1024}; | |
43 | #endif | |
44 | message<isRequest, string_body, fields> m; | |
45 | read(ss, dynabuf, m, ec); | |
46 | if(! BEAST_EXPECTS(! ec, ec.message())) | |
47 | return; | |
48 | pred(m); | |
49 | } | |
50 | ||
51 | void | |
52 | testRead() | |
53 | { | |
54 | testMatrix<false>( | |
55 | "HTTP/1.0 200 OK\r\n" | |
56 | "Server: test\r\n" | |
57 | "\r\n" | |
58 | "*******", | |
59 | [&](message<false, string_body, fields> const& m) | |
60 | { | |
61 | BEAST_EXPECTS(m.body == "*******", | |
62 | "body='" + m.body + "'"); | |
63 | } | |
64 | ); | |
65 | testMatrix<false>( | |
66 | "HTTP/1.0 200 OK\r\n" | |
67 | "Server: test\r\n" | |
68 | "Transfer-Encoding: chunked\r\n" | |
69 | "\r\n" | |
70 | "5\r\n" | |
71 | "*****\r\n" | |
72 | "2;a;b=1;c=\"2\"\r\n" | |
73 | "--\r\n" | |
74 | "0;d;e=3;f=\"4\"\r\n" | |
75 | "Expires: never\r\n" | |
76 | "MD5-Fingerprint: -\r\n" | |
77 | "\r\n", | |
78 | [&](message<false, string_body, fields> const& m) | |
79 | { | |
80 | BEAST_EXPECT(m.body == "*****--"); | |
81 | } | |
82 | ); | |
83 | testMatrix<false>( | |
84 | "HTTP/1.0 200 OK\r\n" | |
85 | "Server: test\r\n" | |
86 | "Content-Length: 5\r\n" | |
87 | "\r\n" | |
88 | "*****", | |
89 | [&](message<false, string_body, fields> const& m) | |
90 | { | |
91 | BEAST_EXPECT(m.body == "*****"); | |
92 | } | |
93 | ); | |
94 | testMatrix<true>( | |
95 | "GET / HTTP/1.1\r\n" | |
96 | "User-Agent: test\r\n" | |
97 | "\r\n", | |
98 | [&](message<true, string_body, fields> const& m) | |
99 | { | |
100 | } | |
101 | ); | |
102 | testMatrix<true>( | |
103 | "GET / HTTP/1.1\r\n" | |
104 | "User-Agent: test\r\n" | |
105 | "X: \t x \t \r\n" | |
106 | "\r\n", | |
107 | [&](message<true, string_body, fields> const& m) | |
108 | { | |
109 | BEAST_EXPECT(m.fields["X"] == "x"); | |
110 | } | |
111 | ); | |
112 | } | |
113 | ||
114 | void | |
115 | testParse() | |
116 | { | |
117 | using boost::asio::buffer; | |
118 | { | |
119 | error_code ec; | |
120 | beast::test::string_istream is{ | |
121 | get_io_service(), | |
122 | "GET / HTTP/1.1\r\n" | |
123 | "User-Agent: test\r\n" | |
124 | "Content-Length: 1\r\n" | |
125 | "\r\n" | |
126 | "*"}; | |
127 | flat_streambuf sb{1024}; | |
128 | message_parser<true, string_body, fields> p; | |
129 | read(is, sb, p, ec); | |
130 | auto const& m = p.get(); | |
131 | BEAST_EXPECTS(! ec, ec.message()); | |
132 | BEAST_EXPECT(p.is_complete()); | |
133 | BEAST_EXPECT(m.method == "GET"); | |
134 | BEAST_EXPECT(m.url == "/"); | |
135 | BEAST_EXPECT(m.version == 11); | |
136 | BEAST_EXPECT(m.fields["User-Agent"] == "test"); | |
137 | BEAST_EXPECT(m.body == "*"); | |
138 | } | |
139 | #if 0 | |
140 | { | |
141 | // test partial parsing of final chunk | |
142 | // parse through the chunk body | |
143 | beast::test::string_istream is{ | |
144 | get_io_service(), ""}; | |
145 | streambuf sb; | |
146 | sb << | |
147 | "PUT / HTTP/1.1\r\n" | |
148 | "Transfer-Encoding: chunked\r\n" | |
149 | "\r\n" | |
150 | "1\r\n" | |
151 | "*"; | |
152 | error_code ec; | |
153 | message_parser<true, string_body, fields> p; | |
154 | read(is, sb, p, ec); | |
155 | BEAST_EXPECT(sb.size() == 0); | |
156 | BEAST_EXPECTS(! ec, ec.message()); | |
157 | BEAST_EXPECT(!p.is_complete()); | |
158 | BEAST_EXPECT(p.get().body == "*"); | |
159 | sb << "\r\n0;d;e=3;f=\"4\"\r\n" | |
160 | "Expires: never\r\n" | |
161 | "MD5-Fingerprint: -\r\n"; | |
162 | // incomplete parse, missing the final crlf | |
163 | BEAST_EXPECT(p.write(sb.data(), ec) == 0); | |
164 | BEAST_EXPECTS(! ec, ec.message()); | |
165 | BEAST_EXPECT(!p.is_complete()); | |
166 | sb << "\r\n"; // final crlf to end message | |
167 | BEAST_EXPECT(p.write(sb.data(), ec) == sb.size()); | |
168 | BEAST_EXPECTS(! ec, ec.message()); | |
169 | BEAST_EXPECT(p.is_complete()); | |
170 | } | |
171 | { | |
172 | error_code ec; | |
173 | message_parser<false, string_body, fields> p; | |
174 | std::string const s = | |
175 | "HTTP/1.1 200 OK\r\n" | |
176 | "Server: test\r\n" | |
177 | "Content-Length: 1\r\n" | |
178 | "\r\n" | |
179 | "*"; | |
180 | p.write(buffer(s), ec); | |
181 | auto const& m = p.get(); | |
182 | BEAST_EXPECTS(! ec, ec.message()); | |
183 | BEAST_EXPECT(p.is_complete()); | |
184 | BEAST_EXPECT(m.status == 200); | |
185 | BEAST_EXPECT(m.reason == "OK"); | |
186 | BEAST_EXPECT(m.version == 11); | |
187 | BEAST_EXPECT(m.fields["Server"] == "test"); | |
188 | BEAST_EXPECT(m.body == "*"); | |
189 | } | |
190 | // skip body | |
191 | { | |
192 | error_code ec; | |
193 | message_parser<false, string_body, fields> p; | |
194 | std::string const s = | |
195 | "HTTP/1.1 200 Connection Established\r\n" | |
196 | "Proxy-Agent: Zscaler/5.1\r\n" | |
197 | "\r\n"; | |
198 | p.skip_body(); | |
199 | p.write(buffer(s), ec); | |
200 | BEAST_EXPECTS(! ec, ec.message()); | |
201 | BEAST_EXPECT(p.is_complete()); | |
202 | } | |
203 | #endif | |
204 | } | |
205 | ||
206 | void | |
207 | testExpect100Continue() | |
208 | { | |
209 | test::string_istream ss{ios_, | |
210 | "POST / HTTP/1.1\r\n" | |
211 | "Expect: 100-continue\r\n" | |
212 | "Content-Length: 5\r\n" | |
213 | "\r\n" | |
214 | "*****"}; | |
215 | streambuf sb; | |
216 | error_code ec; | |
217 | header_parser<true, fields> p0; | |
218 | auto const bytes_used = | |
219 | read_some(ss, sb, p0, ec); | |
220 | sb.consume(bytes_used); | |
221 | BEAST_EXPECTS(! ec, ec.message()); | |
222 | BEAST_EXPECT(p0.state() != parse_state::header); | |
223 | BEAST_EXPECT(! p0.is_complete()); | |
224 | message_parser<true, | |
225 | string_body, fields> p1{std::move(p0)}; | |
226 | read(ss, sb, p1, ec); | |
227 | BEAST_EXPECTS(! ec, ec.message()); | |
228 | BEAST_EXPECT(p1.get().body == "*****"); | |
229 | } | |
230 | ||
231 | void | |
232 | run() override | |
233 | { | |
234 | testRead(); | |
235 | testParse(); | |
236 | testExpect100Continue(); | |
237 | } | |
238 | }; | |
239 | ||
240 | BEAST_DEFINE_TESTSUITE(message_parser,http,beast); | |
241 | ||
242 | } // http | |
243 | } // beast | |
244 |