]>
git.proxmox.com Git - ceph.git/blob - ceph/src/Beast/test/http/basic_parser.cpp
2 // Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
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)
8 // Test that header file is self-contained.
9 #include <beast/http/basic_parser.hpp>
11 #include "test_parser.hpp"
13 #include <beast/core/buffer_cat.hpp>
14 #include <beast/core/consuming_buffers.hpp>
15 #include <beast/core/streambuf.hpp>
16 #include <beast/unit_test/suite.hpp>
21 class basic_parser_test
: public beast::unit_test::suite
27 connection_keep_alive
= 2,
29 connection_upgrade
= 8,
39 expect_version(suite
& s
, int version
)
45 template<class Parser
>
47 operator()(Parser
const& p
) const
49 s_
.BEAST_EXPECT(p
.version
== version_
);
59 expect_status(suite
& s
, int status
)
65 template<class Parser
>
67 operator()(Parser
const& p
) const
69 s_
.BEAST_EXPECT(p
.status
== status_
);
79 expect_flags(suite
& s
, unsigned flags
)
85 template<class Parser
>
87 operator()(Parser
const& p
) const
89 if(flags_
& parse_flag::chunked
)
90 s_
.BEAST_EXPECT(p
.is_chunked());
91 if(flags_
& parse_flag::connection_keep_alive
)
92 s_
.BEAST_EXPECT(p
.is_keep_alive());
93 if(flags_
& parse_flag::connection_close
)
94 s_
.BEAST_EXPECT(! p
.is_keep_alive());
95 if(flags_
& parse_flag::upgrade
)
96 s_
.BEAST_EXPECT(! p
.is_upgrade());
100 class expect_keepalive
106 expect_keepalive(suite
& s
, bool v
)
112 template<class Parser
>
114 operator()(Parser
const& p
) const
116 s_
.BEAST_EXPECT(p
.is_keep_alive() == v_
);
123 std::string
const& body_
;
126 expect_body(expect_body
&&) = default;
128 expect_body(suite
& s
, std::string
const& v
)
134 template<class Parser
>
136 operator()(Parser
const& p
) const
138 s_
.BEAST_EXPECT(p
.body
== body_
);
142 template<std::size_t N
>
144 boost::asio::const_buffers_1
145 buf(char const (&s
)[N
])
151 bool isRequest
, bool isDirect
, class Derived
>
154 feed(boost::asio::const_buffer buffer
,
155 basic_parser
<isRequest
, isDirect
, Derived
>& parser
,
158 using boost::asio::const_buffers_1
;
159 std::size_t used
= 0;
162 auto const n
= parser
.write(
163 const_buffers_1
{buffer
}, ec
);
170 if(parser
.is_complete())
172 if(buffer_size(buffer
) == 0)
178 template<class ConstBufferSequence
,
179 bool isRequest
, bool isDirect
, class Derived
>
182 feed(ConstBufferSequence
const& buffers
,
183 basic_parser
<isRequest
, isDirect
, Derived
>& parser
,
186 using boost::asio::buffer_size
;
188 ConstBufferSequence
> cb
{buffers
};
189 std::size_t used
= 0;
193 parser
.write(cb
, ec
);
200 if(parser
.is_complete())
202 if(buffer_size(cb
) == 0)
209 bool isRequest
, bool isDirect
, class Derived
>
212 feed(boost::asio::const_buffers_1 buffers
,
213 basic_parser
<isRequest
, isDirect
, Derived
>& parser
,
216 return feed(*buffers
.begin(), parser
, ec
);
219 template<bool isRequest
, class Pred
>
221 good(boost::string_ref
const& s
,
222 Pred
const& pred
, bool skipBody
= false)
224 using boost::asio::buffer
;
225 test_parser
<isRequest
> p
;
229 auto const n
= feed(buffer(
230 s
.data(), s
.size()), p
, ec
);
231 if(! BEAST_EXPECTS(! ec
, ec
.message()))
233 if(! BEAST_EXPECT(n
== s
.size()))
235 if(p
.state() == parse_state::body_to_eof
)
237 if(BEAST_EXPECTS(! ec
, ec
.message()))
241 template<bool isRequest
>
243 good(boost::string_ref
const& s
)
246 [](test_parser
<isRequest
> const&)
251 template<bool isRequest
>
253 bad(boost::string_ref
const& s
,
254 error_code
const& ev
, bool skipBody
= false)
256 using boost::asio::buffer
;
257 test_parser
<isRequest
> p
;
262 s
.data(), s
.size()), p
, ec
);
265 BEAST_EXPECTS(ec
== ev
, ec
.message());
271 using boost::asio::buffer
;
273 std::string
const s
=
275 "Content-Length: 1\r\n"
278 for(std::size_t i
= 1;
279 i
< s
.size() - 1; ++i
)
283 auto const b2
= buffer(
284 s
.data() + i
, s
.size() - i
);
288 BEAST_EXPECTS(! ec
, ec
.message());
289 feed(buffer_cat(b1
, b2
), p
, ec
);
290 BEAST_EXPECTS(! ec
, ec
.message());
291 BEAST_EXPECT(p
.is_complete());
295 std::string
const s
=
296 "HTTP/1.1 200 OK\r\n"
298 for(std::size_t i
= 1;
299 i
< s
.size() - 1; ++i
)
303 auto const b2
= buffer(
304 s
.data() + i
, s
.size() - i
);
305 test_parser
<false> p
;
308 BEAST_EXPECTS(! ec
, ec
.message());
310 feed(buffer_cat(b1
, b2
), p
, ec
);
311 BEAST_EXPECTS(! ec
, ec
.message());
317 // Check that all callbacks are invoked
321 using boost::asio::buffer
;
325 std::string
const s
=
327 "User-Agent: test\r\n"
328 "Content-Length: 1\r\n"
331 feed(buffer(s
), p
, ec
);
332 BEAST_EXPECTS(! ec
, ec
.message());
333 BEAST_EXPECT(p
.is_complete());
334 BEAST_EXPECT(p
.got_on_begin
);
335 BEAST_EXPECT(p
.got_on_field
);
336 BEAST_EXPECT(p
.got_on_header
);
337 BEAST_EXPECT(p
.got_on_body
);
338 BEAST_EXPECT(! p
.got_on_chunk
);
339 BEAST_EXPECT(p
.got_on_complete
);
342 test_parser
<false> p
;
344 std::string
const s
=
345 "HTTP/1.1 200 OK\r\n"
347 "Content-Length: 1\r\n"
350 feed(buffer(s
), p
, ec
);
351 BEAST_EXPECTS(! ec
, ec
.message());
352 BEAST_EXPECT(p
.is_complete());
353 BEAST_EXPECT(p
.got_on_begin
);
354 BEAST_EXPECT(p
.got_on_field
);
355 BEAST_EXPECT(p
.got_on_header
);
356 BEAST_EXPECT(p
.got_on_body
);
357 BEAST_EXPECT(! p
.got_on_chunk
);
358 BEAST_EXPECT(p
.got_on_complete
);
365 good
<true>("GET /x HTTP/1.0\r\n\r\n");
366 good
<true>("!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz / HTTP/1.0\r\n\r\n");
367 good
<true>("GET / HTTP/1.0\r\n\r\n", expect_version
{*this, 10});
368 good
<true>("G / HTTP/1.1\r\n\r\n", expect_version
{*this, 11});
369 // VFALCO TODO various forms of good request-target (uri)
370 good
<true>("GET / HTTP/0.1\r\n\r\n", expect_version
{*this, 1});
371 good
<true>("GET / HTTP/2.3\r\n\r\n", expect_version
{*this, 23});
372 good
<true>("GET / HTTP/4.5\r\n\r\n", expect_version
{*this, 45});
373 good
<true>("GET / HTTP/6.7\r\n\r\n", expect_version
{*this, 67});
374 good
<true>("GET / HTTP/8.9\r\n\r\n", expect_version
{*this, 89});
376 bad
<true>("\tGET / HTTP/1.0\r\n" "\r\n", error::bad_method
);
377 bad
<true>("GET\x01 / HTTP/1.0\r\n" "\r\n", error::bad_method
);
378 bad
<true>("GET / HTTP/1.0\r\n" "\r\n", error::bad_path
);
379 bad
<true>("GET \x01 HTTP/1.0\r\n" "\r\n", error::bad_path
);
380 bad
<true>("GET /\x01 HTTP/1.0\r\n" "\r\n", error::bad_path
);
381 // VFALCO TODO various forms of bad request-target (uri)
382 bad
<true>("GET / HTTP/1.0\r\n" "\r\n", error::bad_version
);
383 bad
<true>("GET / _TTP/1.0\r\n" "\r\n", error::bad_version
);
384 bad
<true>("GET / H_TP/1.0\r\n" "\r\n", error::bad_version
);
385 bad
<true>("GET / HT_P/1.0\r\n" "\r\n", error::bad_version
);
386 bad
<true>("GET / HTT_/1.0\r\n" "\r\n", error::bad_version
);
387 bad
<true>("GET / HTTP_1.0\r\n" "\r\n", error::bad_version
);
388 bad
<true>("GET / HTTP/01.2\r\n" "\r\n", error::bad_version
);
389 bad
<true>("GET / HTTP/3.45\r\n" "\r\n", error::bad_version
);
390 bad
<true>("GET / HTTP/67.89\r\n" "\r\n", error::bad_version
);
391 bad
<true>("GET / HTTP/x.0\r\n" "\r\n", error::bad_version
);
392 bad
<true>("GET / HTTP/1.x\r\n" "\r\n", error::bad_version
);
393 bad
<true>("GET / HTTP/1.0 \r\n" "\r\n", error::bad_version
);
394 bad
<true>("GET / HTTP/1_0\r\n" "\r\n", error::bad_version
);
395 bad
<true>("GET / HTTP/1.0\n\r\n" "\r\n", error::bad_version
);
396 bad
<true>("GET / HTTP/1.0\n\r\r\n" "\r\n", error::bad_line_ending
);
397 bad
<true>("GET / HTTP/1.0\r\r\n" "\r\n", error::bad_line_ending
);
403 good
<false>("HTTP/0.1 200 OK\r\n" "\r\n", expect_version
{*this, 1});
404 good
<false>("HTTP/2.3 200 OK\r\n" "\r\n", expect_version
{*this, 23});
405 good
<false>("HTTP/4.5 200 OK\r\n" "\r\n", expect_version
{*this, 45});
406 good
<false>("HTTP/6.7 200 OK\r\n" "\r\n", expect_version
{*this, 67});
407 good
<false>("HTTP/8.9 200 OK\r\n" "\r\n", expect_version
{*this, 89});
408 good
<false>("HTTP/1.0 000 OK\r\n" "\r\n", expect_status
{*this, 0});
409 good
<false>("HTTP/1.1 012 OK\r\n" "\r\n", expect_status
{*this, 12});
410 good
<false>("HTTP/1.0 345 OK\r\n" "\r\n", expect_status
{*this, 345});
411 good
<false>("HTTP/1.0 678 OK\r\n" "\r\n", expect_status
{*this, 678});
412 good
<false>("HTTP/1.0 999 OK\r\n" "\r\n", expect_status
{*this, 999});
413 good
<false>("HTTP/1.0 200 \tX\r\n" "\r\n", expect_version
{*this, 10});
414 good
<false>("HTTP/1.1 200 X\r\n" "\r\n", expect_version
{*this, 11});
415 good
<false>("HTTP/1.0 200 \r\n" "\r\n");
416 good
<false>("HTTP/1.1 200 X \r\n" "\r\n");
417 good
<false>("HTTP/1.1 200 X\t\r\n" "\r\n");
418 good
<false>("HTTP/1.1 200 \x80\x81...\xfe\xff\r\n\r\n");
419 good
<false>("HTTP/1.1 200 !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\r\n\r\n");
421 bad
<false>("\rHTTP/1.0 200 OK\r\n" "\r\n", error::bad_line_ending
);
422 bad
<false>("\nHTTP/1.0 200 OK\r\n" "\r\n", error::bad_version
);
423 bad
<false>(" HTTP/1.0 200 OK\r\n" "\r\n", error::bad_version
);
424 bad
<false>("_TTP/1.0 200 OK\r\n" "\r\n", error::bad_version
);
425 bad
<false>("H_TP/1.0 200 OK\r\n" "\r\n", error::bad_version
);
426 bad
<false>("HT_P/1.0 200 OK\r\n" "\r\n", error::bad_version
);
427 bad
<false>("HTT_/1.0 200 OK\r\n" "\r\n", error::bad_version
);
428 bad
<false>("HTTP_1.0 200 OK\r\n" "\r\n", error::bad_version
);
429 bad
<false>("HTTP/01.2 200 OK\r\n" "\r\n", error::bad_version
);
430 bad
<false>("HTTP/3.45 200 OK\r\n" "\r\n", error::bad_version
);
431 bad
<false>("HTTP/67.89 200 OK\r\n" "\r\n", error::bad_version
);
432 bad
<false>("HTTP/x.0 200 OK\r\n" "\r\n", error::bad_version
);
433 bad
<false>("HTTP/1.x 200 OK\r\n" "\r\n", error::bad_version
);
434 bad
<false>("HTTP/1_0 200 OK\r\n" "\r\n", error::bad_version
);
435 bad
<false>("HTTP/1.0 200 OK\r\n" "\r\n", error::bad_status
);
436 bad
<false>("HTTP/1.0 0 OK\r\n" "\r\n", error::bad_status
);
437 bad
<false>("HTTP/1.0 12 OK\r\n" "\r\n", error::bad_status
);
438 bad
<false>("HTTP/1.0 3456 OK\r\n" "\r\n", error::bad_status
);
439 bad
<false>("HTTP/1.0 200\r\n" "\r\n", error::bad_status
);
440 bad
<false>("HTTP/1.0 200 \n\r\n" "\r\n", error::bad_reason
);
441 bad
<false>("HTTP/1.0 200 \x01\r\n" "\r\n", error::bad_reason
);
442 bad
<false>("HTTP/1.0 200 \x7f\r\n" "\r\n", error::bad_reason
);
443 bad
<false>("HTTP/1.0 200 OK\n\r\n" "\r\n", error::bad_reason
);
444 bad
<false>("HTTP/1.0 200 OK\r\r\n" "\r\n", error::bad_line_ending
);
451 [](std::string
const& s
)
453 return "GET / HTTP/1.1\r\n" + s
+ "\r\n";
455 good
<true>(m("f:\r\n"));
456 good
<true>(m("f: \r\n"));
457 good
<true>(m("f:\t\r\n"));
458 good
<true>(m("f: \t\r\n"));
459 good
<true>(m("f: v\r\n"));
460 good
<true>(m("f:\tv\r\n"));
461 good
<true>(m("f:\tv \r\n"));
462 good
<true>(m("f:\tv\t\r\n"));
463 good
<true>(m("f:\tv\t \r\n"));
464 good
<true>(m("f:\r\n \r\n"));
465 good
<true>(m("f:v\r\n"));
466 good
<true>(m("f: v\r\n u\r\n"));
467 good
<true>(m("!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz: v\r\n"));
468 good
<true>(m("f: !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x80\x81...\xfe\xff\r\n"));
470 bad
<true>(m(" f: v\r\n"), error::bad_field
);
471 bad
<true>(m("\tf: v\r\n"), error::bad_field
);
472 bad
<true>(m("f : v\r\n"), error::bad_field
);
473 bad
<true>(m("f\t: v\r\n"), error::bad_field
);
474 bad
<true>(m("f: \n\r\n"), error::bad_value
);
475 bad
<true>(m("f: v\r \r\n"), error::bad_line_ending
);
476 bad
<true>(m("f: \r v\r\n"), error::bad_line_ending
);
477 bad
<true>("GET / HTTP/1.1\r\n\r \n\r\n\r\n",error::bad_line_ending
);
481 testConnectionField()
484 [](std::string
const& s
)
486 return "GET / HTTP/1.1\r\n" + s
+ "\r\n";
489 [](std::string
const& s
)
491 return "GET / HTTP/1.1\r\nConnection: " + s
+ "\r\n";
494 auto const keepalive
=
497 //return keepalive_f{*this, v};
502 good
<true>(cn("close\r\n"), expect_flags
{*this, parse_flag::connection_close
});
503 good
<true>(cn(",close\r\n"), expect_flags
{*this, parse_flag::connection_close
});
504 good
<true>(cn(" close\r\n"), expect_flags
{*this, parse_flag::connection_close
});
505 good
<true>(cn("\tclose\r\n"), expect_flags
{*this, parse_flag::connection_close
});
506 good
<true>(cn("close,\r\n"), expect_flags
{*this, parse_flag::connection_close
});
507 good
<true>(cn("close\t\r\n"), expect_flags
{*this, parse_flag::connection_close
});
508 good
<true>(cn("close\r\n"), expect_flags
{*this, parse_flag::connection_close
});
509 good
<true>(cn(" ,\t,,close,, ,\t,,\r\n"), expect_flags
{*this, parse_flag::connection_close
});
510 good
<true>(cn("\r\n close\r\n"), expect_flags
{*this, parse_flag::connection_close
});
511 good
<true>(cn("close\r\n \r\n"), expect_flags
{*this, parse_flag::connection_close
});
512 good
<true>(cn("any,close\r\n"), expect_flags
{*this, parse_flag::connection_close
});
513 good
<true>(cn("close,any\r\n"), expect_flags
{*this, parse_flag::connection_close
});
514 good
<true>(cn("any\r\n ,close\r\n"), expect_flags
{*this, parse_flag::connection_close
});
515 good
<true>(cn("close\r\n ,any\r\n"), expect_flags
{*this, parse_flag::connection_close
});
516 good
<true>(cn("close,close\r\n"), expect_flags
{*this, parse_flag::connection_close
}); // weird but allowed
518 good
<true>(cn("keep-alive\r\n"), expect_flags
{*this, parse_flag::connection_keep_alive
});
519 good
<true>(cn("keep-alive \r\n"), expect_flags
{*this, parse_flag::connection_keep_alive
});
520 good
<true>(cn("keep-alive\t \r\n"), expect_flags
{*this, parse_flag::connection_keep_alive
});
521 good
<true>(cn("keep-alive\t ,x\r\n"), expect_flags
{*this, parse_flag::connection_keep_alive
});
522 good
<true>(cn("\r\n keep-alive \t\r\n"), expect_flags
{*this, parse_flag::connection_keep_alive
});
523 good
<true>(cn("keep-alive \r\n \t \r\n"), expect_flags
{*this, parse_flag::connection_keep_alive
});
524 good
<true>(cn("keep-alive\r\n \r\n"), expect_flags
{*this, parse_flag::connection_keep_alive
});
526 good
<true>(cn("upgrade\r\n"), expect_flags
{*this, parse_flag::connection_upgrade
});
527 good
<true>(cn("upgrade \r\n"), expect_flags
{*this, parse_flag::connection_upgrade
});
528 good
<true>(cn("upgrade\t \r\n"), expect_flags
{*this, parse_flag::connection_upgrade
});
529 good
<true>(cn("upgrade\t ,x\r\n"), expect_flags
{*this, parse_flag::connection_upgrade
});
530 good
<true>(cn("\r\n upgrade \t\r\n"), expect_flags
{*this, parse_flag::connection_upgrade
});
531 good
<true>(cn("upgrade \r\n \t \r\n"), expect_flags
{*this, parse_flag::connection_upgrade
});
532 good
<true>(cn("upgrade\r\n \r\n"), expect_flags
{*this, parse_flag::connection_upgrade
});
534 // VFALCO What's up with these?
535 //good<true>(cn("close,keep-alive\r\n"), expect_flags{*this, parse_flag::connection_close | parse_flag::connection_keep_alive});
536 good
<true>(cn("upgrade,keep-alive\r\n"), expect_flags
{*this, parse_flag::connection_upgrade
| parse_flag::connection_keep_alive
});
537 good
<true>(cn("upgrade,\r\n keep-alive\r\n"), expect_flags
{*this, parse_flag::connection_upgrade
| parse_flag::connection_keep_alive
});
538 //good<true>(cn("close,keep-alive,upgrade\r\n"), expect_flags{*this, parse_flag::connection_close | parse_flag::connection_keep_alive | parse_flag::connection_upgrade});
540 good
<true>("GET / HTTP/1.1\r\n\r\n", expect_keepalive(*this, true));
541 good
<true>("GET / HTTP/1.0\r\n\r\n", expect_keepalive(*this, false));
542 good
<true>("GET / HTTP/1.0\r\n"
543 "Connection: keep-alive\r\n\r\n", expect_keepalive(*this, true));
544 good
<true>("GET / HTTP/1.1\r\n"
545 "Connection: close\r\n\r\n", expect_keepalive(*this, false));
547 good
<true>(cn("x\r\n"), expect_flags
{*this, 0});
548 good
<true>(cn("x,y\r\n"), expect_flags
{*this, 0});
549 good
<true>(cn("x ,y\r\n"), expect_flags
{*this, 0});
550 good
<true>(cn("x\t,y\r\n"), expect_flags
{*this, 0});
551 good
<true>(cn("keep\r\n"), expect_flags
{*this, 0});
552 good
<true>(cn(",keep\r\n"), expect_flags
{*this, 0});
553 good
<true>(cn(" keep\r\n"), expect_flags
{*this, 0});
554 good
<true>(cn("\tnone\r\n"), expect_flags
{*this, 0});
555 good
<true>(cn("keep,\r\n"), expect_flags
{*this, 0});
556 good
<true>(cn("keep\t\r\n"), expect_flags
{*this, 0});
557 good
<true>(cn("keep\r\n"), expect_flags
{*this, 0});
558 good
<true>(cn(" ,\t,,keep,, ,\t,,\r\n"), expect_flags
{*this, 0});
559 good
<true>(cn("\r\n keep\r\n"), expect_flags
{*this, 0});
560 good
<true>(cn("keep\r\n \r\n"), expect_flags
{*this, 0});
561 good
<true>(cn("closet\r\n"), expect_flags
{*this, 0});
562 good
<true>(cn(",closet\r\n"), expect_flags
{*this, 0});
563 good
<true>(cn(" closet\r\n"), expect_flags
{*this, 0});
564 good
<true>(cn("\tcloset\r\n"), expect_flags
{*this, 0});
565 good
<true>(cn("closet,\r\n"), expect_flags
{*this, 0});
566 good
<true>(cn("closet\t\r\n"), expect_flags
{*this, 0});
567 good
<true>(cn("closet\r\n"), expect_flags
{*this, 0});
568 good
<true>(cn(" ,\t,,closet,, ,\t,,\r\n"), expect_flags
{*this, 0});
569 good
<true>(cn("\r\n closet\r\n"), expect_flags
{*this, 0});
570 good
<true>(cn("closet\r\n \r\n"), expect_flags
{*this, 0});
571 good
<true>(cn("clog\r\n"), expect_flags
{*this, 0});
572 good
<true>(cn("key\r\n"), expect_flags
{*this, 0});
573 good
<true>(cn("uptown\r\n"), expect_flags
{*this, 0});
574 good
<true>(cn("keeper\r\n \r\n"), expect_flags
{*this, 0});
575 good
<true>(cn("keep-alively\r\n \r\n"), expect_flags
{*this, 0});
576 good
<true>(cn("up\r\n \r\n"), expect_flags
{*this, 0});
577 good
<true>(cn("upgrader\r\n \r\n"), expect_flags
{*this, 0});
578 good
<true>(cn("none\r\n"), expect_flags
{*this, 0});
579 good
<true>(cn("\r\n none\r\n"), expect_flags
{*this, 0});
581 good
<true>(m("ConnectioX: close\r\n"), expect_flags
{*this, 0});
582 good
<true>(m("Condor: close\r\n"), expect_flags
{*this, 0});
583 good
<true>(m("Connect: close\r\n"), expect_flags
{*this, 0});
584 good
<true>(m("Connections: close\r\n"), expect_flags
{*this, 0});
586 good
<true>(m("Proxy-Connection: close\r\n"), expect_flags
{*this, parse_flag::connection_close
});
587 good
<true>(m("Proxy-Connection: keep-alive\r\n"), expect_flags
{*this, parse_flag::connection_keep_alive
});
588 good
<true>(m("Proxy-Connection: upgrade\r\n"), expect_flags
{*this, parse_flag::connection_upgrade
});
589 good
<true>(m("Proxy-ConnectioX: none\r\n"), expect_flags
{*this, 0});
590 good
<true>(m("Proxy-Connections: 1\r\n"), expect_flags
{*this, 0});
591 good
<true>(m("Proxy-Connotes: see-also\r\n"), expect_flags
{*this, 0});
593 bad
<true>(cn("[\r\n"), error::bad_value
);
594 bad
<true>(cn("close[\r\n"), error::bad_value
);
595 bad
<true>(cn("close [\r\n"), error::bad_value
);
596 bad
<true>(cn("close, upgrade [\r\n"), error::bad_value
);
597 bad
<true>(cn("upgrade[]\r\n"), error::bad_value
);
598 bad
<true>(cn("keep\r\n -alive\r\n"), error::bad_value
);
599 bad
<true>(cn("keep-alive[\r\n"), error::bad_value
);
600 bad
<true>(cn("keep-alive []\r\n"), error::bad_value
);
601 bad
<true>(cn("no[ne]\r\n"), error::bad_value
);
605 testContentLengthField()
608 [&](std::string
const& s
, std::uint64_t v
)
611 [&](test_parser
<true> const& p
)
613 BEAST_EXPECT(p
.content_length());
614 BEAST_EXPECT(p
.content_length() && *p
.content_length() == v
);
618 [](std::string
const& s
)
620 return "GET / HTTP/1.1\r\nContent-Length: " + s
+ "\r\n";
623 [](std::string
const& s
)
625 return "GET / HTTP/1.1\r\n" + s
+ "\r\n";
628 length(c("0\r\n"), 0);
629 length(c("00\r\n"), 0);
630 length(c("1\r\n"), 1);
631 length(c("01\r\n"), 1);
632 length(c("9\r\n"), 9);
633 length(c("123456789\r\n"), 123456789);
634 length(c("42 \r\n"), 42);
635 length(c("42\t\r\n"), 42);
636 length(c("42 \t \r\n"), 42);
638 // VFALCO Investigate this failure
639 //length(c("42\r\n \t \r\n"), 42);
641 good
<true>(m("Content-LengtX: 0\r\n"), expect_flags
{*this, 0});
642 good
<true>(m("Content-Lengths: many\r\n"), expect_flags
{*this, 0});
643 good
<true>(m("Content: full\r\n"), expect_flags
{*this, 0});
645 bad
<true>(c("\r\n"), error::bad_content_length
);
646 bad
<true>(c("18446744073709551616\r\n"), error::bad_content_length
);
647 bad
<true>(c("0 0\r\n"), error::bad_content_length
);
648 bad
<true>(c("0 1\r\n"), error::bad_content_length
);
649 bad
<true>(c(",\r\n"), error::bad_content_length
);
650 bad
<true>(c("0,\r\n"), error::bad_content_length
);
652 "Content-Length: 0\r\nContent-Length: 0\r\n"), error::bad_content_length
);
656 testTransferEncodingField()
659 [](std::string
const& s
)
661 return "GET / HTTP/1.1\r\n" + s
+ "\r\n";
664 [](std::string
const& s
)
666 return "GET / HTTP/1.1\r\nTransfer-Encoding: " + s
+ "\r\n0\r\n\r\n";
669 [](std::string
const& s
)
671 return "GET / HTTP/1.1\r\nTransfer-Encoding: " + s
+ "\r\n";
673 good
<true>(ce("chunked\r\n"), expect_flags
{*this, parse_flag::chunked
});
674 good
<true>(ce("chunked \r\n"), expect_flags
{*this, parse_flag::chunked
});
675 good
<true>(ce("chunked\t\r\n"), expect_flags
{*this, parse_flag::chunked
});
676 good
<true>(ce("chunked \t\r\n"), expect_flags
{*this, parse_flag::chunked
});
677 good
<true>(ce(" chunked\r\n"), expect_flags
{*this, parse_flag::chunked
});
678 good
<true>(ce("\tchunked\r\n"), expect_flags
{*this, parse_flag::chunked
});
679 good
<true>(ce("chunked,\r\n"), expect_flags
{*this, parse_flag::chunked
});
680 good
<true>(ce("chunked ,\r\n"), expect_flags
{*this, parse_flag::chunked
});
681 good
<true>(ce("chunked, \r\n"), expect_flags
{*this, parse_flag::chunked
});
682 good
<true>(ce(",chunked\r\n"), expect_flags
{*this, parse_flag::chunked
});
683 good
<true>(ce(", chunked\r\n"), expect_flags
{*this, parse_flag::chunked
});
684 good
<true>(ce(" ,chunked\r\n"), expect_flags
{*this, parse_flag::chunked
});
685 good
<true>(ce("chunked\r\n \r\n"), expect_flags
{*this, parse_flag::chunked
});
686 good
<true>(ce("\r\n chunked\r\n"), expect_flags
{*this, parse_flag::chunked
});
687 good
<true>(ce(",\r\n chunked\r\n"), expect_flags
{*this, parse_flag::chunked
});
688 good
<true>(ce("\r\n ,chunked\r\n"), expect_flags
{*this, parse_flag::chunked
});
689 good
<true>(ce(",\r\n chunked\r\n"), expect_flags
{*this, parse_flag::chunked
});
690 good
<true>(ce("gzip, chunked\r\n"), expect_flags
{*this, parse_flag::chunked
});
691 good
<true>(ce("gzip, chunked \r\n"), expect_flags
{*this, parse_flag::chunked
});
692 good
<true>(ce("gzip, \r\n chunked\r\n"), expect_flags
{*this, parse_flag::chunked
});
694 // Technically invalid but beyond the parser's scope to detect
695 // VFALCO Look into this
696 //good<true>(ce("custom;key=\",chunked\r\n"), expect_flags{*this, parse_flag::chunked});
698 good
<true>(te("gzip\r\n"), expect_flags
{*this, 0});
699 good
<true>(te("chunked, gzip\r\n"), expect_flags
{*this, 0});
700 good
<true>(te("chunked\r\n , gzip\r\n"), expect_flags
{*this, 0});
701 good
<true>(te("chunked,\r\n gzip\r\n"), expect_flags
{*this, 0});
702 good
<true>(te("chunked,\r\n ,gzip\r\n"), expect_flags
{*this, 0});
703 good
<true>(te("bigchunked\r\n"), expect_flags
{*this, 0});
704 good
<true>(te("chunk\r\n ked\r\n"), expect_flags
{*this, 0});
705 good
<true>(te("bar\r\n ley chunked\r\n"), expect_flags
{*this, 0});
706 good
<true>(te("barley\r\n chunked\r\n"), expect_flags
{*this, 0});
708 good
<true>(m("Transfer-EncodinX: none\r\n"), expect_flags
{*this, 0});
709 good
<true>(m("Transfer-Encodings: 2\r\n"), expect_flags
{*this, 0});
710 good
<true>(m("Transfer-Encoded: false\r\n"), expect_flags
{*this, 0});
713 "HTTP/1.1 200 OK\r\n"
714 "Content-Length: 1\r\n"
715 "Transfer-Encoding: chunked\r\n"
716 "\r\n", error::bad_transfer_encoding
, true);
723 [](std::string
const& s
)
725 return "GET / HTTP/1.1\r\n" + s
+ "\r\n";
727 good
<true>(m("Upgrade:\r\n"), expect_flags
{*this, parse_flag::upgrade
});
728 good
<true>(m("Upgrade: \r\n"), expect_flags
{*this, parse_flag::upgrade
});
729 good
<true>(m("Upgrade: yes\r\n"), expect_flags
{*this, parse_flag::upgrade
});
731 good
<true>(m("Up: yes\r\n"), expect_flags
{*this, 0});
732 good
<true>(m("UpgradX: none\r\n"), expect_flags
{*this, 0});
733 good
<true>(m("Upgrades: 2\r\n"), expect_flags
{*this, 0});
734 good
<true>(m("Upsample: 4x\r\n"), expect_flags
{*this, 0});
738 "Connection: upgrade\r\n"
739 "Upgrade: WebSocket\r\n"
741 [&](test_parser
<true> const& p
)
743 BEAST_EXPECT(p
.is_upgrade());
749 using boost::asio::buffer
;
752 "Content-Length: 1\r\n"
755 expect_body(*this, "1"));
758 "HTTP/1.0 200 OK\r\n"
761 expect_body(*this, "hello"));
763 // write the body in 3 pieces
768 buf("GET / HTTP/1.1\r\n"
769 "Content-Length: 10\r\n"
775 BEAST_EXPECTS(! ec
, ec
.message());
776 BEAST_EXPECT(p
.is_complete());
779 // request without Content-Length or
780 // Transfer-Encoding: chunked has no body.
788 BEAST_EXPECTS(! ec
, ec
.message());
789 BEAST_EXPECT(p
.is_complete());
798 BEAST_EXPECTS(! ec
, ec
.message());
799 BEAST_EXPECT(p
.is_complete());
802 // response without Content-Length or
803 // Transfer-Encoding: chunked requires eof.
806 test_parser
<false> p
;
808 "HTTP/1.0 200 OK\r\n"
811 BEAST_EXPECTS(! ec
, ec
.message());
812 BEAST_EXPECT(! p
.is_complete());
813 BEAST_EXPECT(p
.state() == parse_state::body_to_eof
);
817 BEAST_EXPECTS(! ec
, ec
.message());
818 BEAST_EXPECT(! p
.is_complete());
819 BEAST_EXPECT(p
.state() == parse_state::body_to_eof
);
821 BEAST_EXPECTS(! ec
, ec
.message());
822 BEAST_EXPECT(p
.is_complete());
825 // 304 "Not Modified" response does not require eof
828 test_parser
<false> p
;
830 "HTTP/1.0 304 Not Modified\r\n"
833 BEAST_EXPECTS(! ec
, ec
.message());
834 BEAST_EXPECT(p
.is_complete());
837 // Chunked response does not require eof
840 test_parser
<false> p
;
842 "HTTP/1.1 200 OK\r\n"
843 "Transfer-Encoding: chunked\r\n"
846 BEAST_EXPECTS(! ec
, ec
.message());
847 BEAST_EXPECT(! p
.is_complete());
851 BEAST_EXPECTS(! ec
, ec
.message());
852 BEAST_EXPECT(p
.is_complete());
855 // restart: 1.0 assumes Connection: close
863 BEAST_EXPECTS(! ec
, ec
.message());
864 BEAST_EXPECT(p
.is_complete());
867 // restart: 1.1 assumes Connection: keep-alive
875 BEAST_EXPECTS(! ec
, ec
.message());
876 BEAST_EXPECT(p
.is_complete());
881 "Content-Length: 1\r\n"
883 error::partial_message
);
886 template<bool isRequest
>
889 test_parser
<isRequest
> const& p
)
891 BEAST_EXPECT(p
.got_on_begin
);
892 BEAST_EXPECT(p
.got_on_field
);
893 BEAST_EXPECT(p
.got_on_header
);
894 BEAST_EXPECT(! p
.got_on_body
);
895 BEAST_EXPECT(! p
.got_on_chunk
);
896 BEAST_EXPECT(! p
.got_on_end_body
);
897 BEAST_EXPECT(! p
.got_on_complete
);
898 BEAST_EXPECT(p
.state() != parse_state::header
);
907 "POST / HTTP/1.1\r\n"
908 "Content-Length: 5\r\n"
914 auto n
= feed(sb
.data(), p
, ec
);
915 BEAST_EXPECTS(! ec
, ec
.message());
916 BEAST_EXPECT(p
.got_on_begin
);
917 BEAST_EXPECT(p
.got_on_field
);
918 BEAST_EXPECT(p
.got_on_header
);
919 BEAST_EXPECT(! p
.got_on_body
);
920 BEAST_EXPECT(! p
.got_on_chunk
);
921 BEAST_EXPECT(! p
.got_on_complete
);
922 BEAST_EXPECT(p
.state() != parse_state::header
);
923 BEAST_EXPECT(! p
.is_complete());
924 BEAST_EXPECT(p
.body
.empty());
927 n
= feed(sb
.data(), p
, ec
);
928 BEAST_EXPECTS(! ec
, ec
.message());
929 BEAST_EXPECT(p
.got_on_begin
);
930 BEAST_EXPECT(p
.got_on_field
);
931 BEAST_EXPECT(p
.got_on_header
);
932 BEAST_EXPECT(p
.got_on_body
);
933 BEAST_EXPECT(! p
.got_on_chunk
);
934 BEAST_EXPECT(p
.got_on_complete
);
935 BEAST_EXPECT(p
.is_complete());
936 BEAST_EXPECT(p
.body
== "*****");
948 testConnectionField();
949 testContentLengthField();
950 testTransferEncodingField();
957 BEAST_DEFINE_TESTSUITE(basic_parser
,http
,beast
);