mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-26 14:05:51 +00:00
New http::client_session for making requests:
- Add 10,000 popular URL data set for unit tests
This commit is contained in:
@@ -70,7 +70,6 @@
|
||||
<None Include="..\..\scripts\compile.sh" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\BeastConfig.h" />
|
||||
<ClInclude Include="..\..\beast\Arithmetic.h" />
|
||||
<ClInclude Include="..\..\beast\asio\abstract_socket.h" />
|
||||
<ClInclude Include="..\..\beast\asio\bind_handler.h" />
|
||||
@@ -150,10 +149,15 @@
|
||||
<ClInclude Include="..\..\beast\cxx14\utility.h" />
|
||||
<ClInclude Include="..\..\beast\HeapBlock.h" />
|
||||
<ClInclude Include="..\..\beast\http\basic_message.h" />
|
||||
<ClInclude Include="..\..\beast\http\basic_url.h" />
|
||||
<ClInclude Include="..\..\beast\http\client_session.h" />
|
||||
<ClInclude Include="..\..\beast\http\detail\header_traits.h" />
|
||||
<ClInclude Include="..\..\beast\http\get.h" />
|
||||
<ClInclude Include="..\..\beast\http\impl\http-parser\http_parser.h" />
|
||||
<ClInclude Include="..\..\beast\http\impl\joyent_parser.h" />
|
||||
<ClInclude Include="..\..\beast\http\ParsedURL.h" />
|
||||
<ClInclude Include="..\..\beast\http\raw_parser.h" />
|
||||
<ClInclude Include="..\..\beast\http\tests\urls_large_data.h" />
|
||||
<ClInclude Include="..\..\beast\http\URL.h" />
|
||||
<ClInclude Include="..\..\beast\Insight.h" />
|
||||
<ClInclude Include="..\..\beast\insight\Base.h" />
|
||||
@@ -257,6 +261,7 @@
|
||||
<ClInclude Include="..\..\beast\utility\type_name.h" />
|
||||
<ClInclude Include="..\..\beast\utility\zero.h" />
|
||||
<ClInclude Include="..\..\beast\Version.h" />
|
||||
<ClInclude Include="..\..\BeastConfig.h" />
|
||||
<ClInclude Include="..\..\modules\beast_asio\async\AsyncObject.h" />
|
||||
<ClInclude Include="..\..\modules\beast_asio\basics\FixedInputBuffer.h" />
|
||||
<ClInclude Include="..\..\modules\beast_asio\basics\PeerRole.h" />
|
||||
@@ -525,6 +530,18 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\http\HTTP.unity.cpp" />
|
||||
<ClCompile Include="..\..\beast\http\impl\basic_url.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\http\impl\get.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\http\impl\raw_parser.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
@@ -573,7 +590,31 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\http\tests\ParsedURL.test.cpp">
|
||||
<ClCompile Include="..\..\beast\http\tests\basic_url.test.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\http\tests\basic_message.test.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\http\tests\client_session.test.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\http\tests\ParsedURL.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\http\tests\urls_large_data.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
|
||||
@@ -274,6 +274,12 @@
|
||||
<Filter Include="beast\streams">
|
||||
<UniqueIdentifier>{899ea9a6-1969-4cde-b26d-8ad60acebfa4}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="beast\http\tests">
|
||||
<UniqueIdentifier>{f95a83a1-5d46-48f9-9877-1d04a525b18e}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="beast\http\detail">
|
||||
<UniqueIdentifier>{7bf4f91a-a7ee-4095-9be3-c1627b8adf02}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="beast\utility\tests">
|
||||
<UniqueIdentifier>{3c58ba5e-1855-4865-8a9f-c0afd5014e74}</UniqueIdentifier>
|
||||
</Filter>
|
||||
@@ -1114,11 +1120,14 @@
|
||||
<ClInclude Include="..\..\beast\streams\abstract_ostream.h">
|
||||
<Filter>beast\streams</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\beast\streams\basic_abstract_ostream.h">
|
||||
<Filter>beast\streams</Filter>
|
||||
<ClInclude Include="..\..\beast\http\client_session.h">
|
||||
<Filter>beast\http</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\beast\streams\basic_scoped_ostream.h">
|
||||
<Filter>beast\streams</Filter>
|
||||
<ClInclude Include="..\..\beast\http\tests\urls_large_data.h">
|
||||
<Filter>beast\http\tests</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\beast\http\detail\header_traits.h">
|
||||
<Filter>beast\http\detail</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\beast\utility\maybe_const.h">
|
||||
<Filter>beast\utility</Filter>
|
||||
@@ -1210,6 +1219,18 @@
|
||||
<ClInclude Include="..\..\beast\utility\ci_char_traits.h">
|
||||
<Filter>beast\utility</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\beast\streams\basic_scoped_ostream.h">
|
||||
<Filter>beast\streams</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\beast\streams\basic_abstract_ostream.h">
|
||||
<Filter>beast\streams</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\beast\http\basic_url.h">
|
||||
<Filter>beast\http</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\beast\http\get.h">
|
||||
<Filter>beast\http</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\modules\beast_core\files\DirectoryIterator.cpp">
|
||||
@@ -1446,9 +1467,6 @@
|
||||
<ClCompile Include="..\..\beast\http\impl\URL.cpp">
|
||||
<Filter>beast\http\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\http\impl\ParsedURL.cpp">
|
||||
<Filter>beast\http\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\crypto\impl\sha2\sha2.c">
|
||||
<Filter>beast\crypto\impl\sha2</Filter>
|
||||
</ClCompile>
|
||||
@@ -1593,15 +1611,21 @@
|
||||
<ClCompile Include="..\..\beast\chrono\impl\chrono_io.cpp">
|
||||
<Filter>beast\chrono\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\http\tests\ParsedURL.test.cpp">
|
||||
<Filter>beast\http\tests</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\net\tests\IPEndpoint.test.cpp">
|
||||
<Filter>beast\net\tests</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\streams\tests\basic_abstract_ostream.test.cpp">
|
||||
<Filter>beast\streams\tests</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\http\tests\urls_large_data.cpp">
|
||||
<Filter>beast\http\tests</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\http\tests\basic_message.test.cpp">
|
||||
<Filter>beast\http\tests</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\http\tests\client_session.test.cpp">
|
||||
<Filter>beast\http\tests</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\threads\tests\Atomic.test.cpp">
|
||||
<Filter>beast\threads\tests</Filter>
|
||||
</ClCompile>
|
||||
@@ -1674,6 +1698,21 @@
|
||||
<ClCompile Include="..\..\modules\beast_sqlite\beast_sqlite.unity.c">
|
||||
<Filter>beast_sqlite</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\http\tests\basic_url.test.cpp">
|
||||
<Filter>beast\http\tests</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\http\impl\basic_url.cpp">
|
||||
<Filter>beast\http\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\http\impl\ParsedURL.cpp">
|
||||
<Filter>beast\http\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\http\tests\ParsedURL.cpp">
|
||||
<Filter>beast\http\tests</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\http\impl\get.cpp">
|
||||
<Filter>beast\http\impl</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="..\..\TODO.txt">
|
||||
|
||||
@@ -21,9 +21,14 @@
|
||||
#include "../../BeastConfig.h"
|
||||
#endif
|
||||
|
||||
#include "impl/URL.cpp"
|
||||
#include "impl/ParsedURL.cpp"
|
||||
#include "impl/basic_url.cpp"
|
||||
#include "impl/get.cpp"
|
||||
#include "impl/joyent_parser.cpp"
|
||||
#include "impl/ParsedURL.cpp"
|
||||
#include "impl/raw_parser.cpp"
|
||||
#include "impl/URL.cpp"
|
||||
|
||||
#include "tests/basic_url.test.cpp"
|
||||
#include "tests/client_session.test.cpp"
|
||||
#include "tests/ParsedURL.cpp"
|
||||
#include "tests/urls_large_data.cpp"
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_HTTP_BASIC_MESSAGE_H_INCLUDED
|
||||
#define BEAST_ASIO_HTTP_BASIC_MESSAGE_H_INCLUDED
|
||||
#ifndef BEAST_HTTP_BASIC_MESSAGE_H_INCLUDED
|
||||
#define BEAST_HTTP_BASIC_MESSAGE_H_INCLUDED
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
||||
174
beast/http/basic_url.h
Normal file
174
beast/http/basic_url.h
Normal file
@@ -0,0 +1,174 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_HTTP_BASIC_URL_H_INCLUDED
|
||||
#define BEAST_HTTP_BASIC_URL_H_INCLUDED
|
||||
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
|
||||
#include "../utility/noexcept.h"
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
namespace detail {
|
||||
|
||||
class basic_url_base
|
||||
{
|
||||
public:
|
||||
typedef char value_type;
|
||||
typedef std::char_traits <value_type> traits_type;
|
||||
|
||||
typedef boost::basic_string_ref <
|
||||
value_type, traits_type> string_ref;
|
||||
|
||||
string_ref
|
||||
scheme () const noexcept
|
||||
{
|
||||
return m_scheme;
|
||||
}
|
||||
|
||||
string_ref
|
||||
host () const noexcept
|
||||
{
|
||||
return m_host;
|
||||
}
|
||||
|
||||
std::uint16_t
|
||||
port () const noexcept
|
||||
{
|
||||
return m_port;
|
||||
}
|
||||
|
||||
string_ref
|
||||
port_string () const noexcept
|
||||
{
|
||||
return m_port_string;
|
||||
}
|
||||
|
||||
string_ref
|
||||
path () const noexcept
|
||||
{
|
||||
return m_path;
|
||||
}
|
||||
|
||||
string_ref
|
||||
query () const noexcept
|
||||
{
|
||||
return m_query;
|
||||
}
|
||||
|
||||
string_ref
|
||||
fragment () const noexcept
|
||||
{
|
||||
return m_fragment;
|
||||
}
|
||||
|
||||
string_ref
|
||||
userinfo () const noexcept
|
||||
{
|
||||
return m_userinfo;
|
||||
}
|
||||
|
||||
protected:
|
||||
void
|
||||
parse_impl (string_ref s, boost::system::error_code& ec);
|
||||
|
||||
string_ref m_string_ref;
|
||||
string_ref m_scheme;
|
||||
string_ref m_host;
|
||||
std::uint16_t m_port;
|
||||
string_ref m_port_string;
|
||||
string_ref m_path;
|
||||
string_ref m_query;
|
||||
string_ref m_fragment;
|
||||
string_ref m_userinfo;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/** A URL. */
|
||||
template <
|
||||
class Alloc = std::allocator <char>
|
||||
>
|
||||
class basic_url : public detail::basic_url_base
|
||||
{
|
||||
public:
|
||||
typedef std::basic_string <
|
||||
value_type, traits_type, Alloc> string_type;
|
||||
|
||||
basic_url() = default;
|
||||
|
||||
explicit basic_url (Alloc const& alloc)
|
||||
: m_string (alloc)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
parse (string_ref s)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
parse (s, ec);
|
||||
if (ec)
|
||||
throw std::invalid_argument ("invalid url string");
|
||||
}
|
||||
|
||||
boost::system::error_code
|
||||
parse (string_ref s,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
parse_impl (s, ec);
|
||||
if (!ec)
|
||||
{
|
||||
m_string = string_type (s.begin(), s.end());
|
||||
m_string_ref = m_string;
|
||||
}
|
||||
return ec;
|
||||
}
|
||||
|
||||
bool
|
||||
empty () const noexcept
|
||||
{
|
||||
return m_string.empty();
|
||||
}
|
||||
|
||||
template <class Alloc1, class Alloc2>
|
||||
friend
|
||||
int
|
||||
compare (basic_url const& lhs,
|
||||
basic_url const& rhs) noexcept
|
||||
{
|
||||
return lhs.m_buf.compare (rhs.m_buf);
|
||||
}
|
||||
|
||||
private:
|
||||
string_type m_string;
|
||||
};
|
||||
|
||||
using url = basic_url <std::allocator <char>>;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
727
beast/http/client_session.h
Normal file
727
beast/http/client_session.h
Normal file
@@ -0,0 +1,727 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_HTTP_BASIC_SESSION_H_INCLUDED
|
||||
#define BEAST_ASIO_HTTP_BASIC_SESSION_H_INCLUDED
|
||||
|
||||
#include "basic_url.h"
|
||||
#include "raw_parser.h"
|
||||
#include "detail/header_traits.h"
|
||||
|
||||
#include "../asio/bind_handler.h"
|
||||
#include "../asio/enable_wait_for_async.h"
|
||||
#include "../asio/placeholders.h"
|
||||
#include "../asio/shared_handler.h"
|
||||
#include "../utility/is_call_possible.h"
|
||||
#include "../utility/ci_char_traits.h"
|
||||
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/asio/deadline_timer.hpp>
|
||||
#include <boost/asio/error.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/socket_base.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <boost/asio/streambuf.hpp>
|
||||
//#include <boost/optional.hpp>
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
#include <boost/logic/tribool.hpp>
|
||||
|
||||
#include "../cxx14/memory.h" // <memory>
|
||||
#include "../cxx14/type_traits.h" // <type_traits>
|
||||
|
||||
#include <sstream> // REMOVE ASAP!
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
template <class T, class Alloc>
|
||||
boost::asio::basic_streambuf <Alloc>&
|
||||
operator<< (boost::asio::basic_streambuf <Alloc>& stream, T const& t)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << t;
|
||||
std::string const s (ss.str());
|
||||
auto const b (boost::asio::buffer (s));
|
||||
auto const len (boost::asio::buffer_size (b));
|
||||
boost::asio::buffer_copy (stream.prepare (len), b);
|
||||
stream.commit (len);
|
||||
return stream;
|
||||
}
|
||||
|
||||
template <class Alloc>
|
||||
boost::asio::basic_streambuf <Alloc>&
|
||||
operator<< (boost::asio::basic_streambuf <Alloc>& stream,
|
||||
std::string const& s)
|
||||
{
|
||||
auto const b (boost::asio::buffer (s));
|
||||
auto const len (boost::asio::buffer_size (b));
|
||||
boost::asio::buffer_copy (stream.prepare (len), b);
|
||||
stream.commit (len);
|
||||
return stream;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4100) // unreferenced formal parameter
|
||||
#endif
|
||||
|
||||
/** Provides asynchronous HTTP client service on a socket. */
|
||||
template <class Socket>
|
||||
class client_session
|
||||
: public asio::enable_wait_for_async <client_session <Socket>>
|
||||
, private raw_parser::callback
|
||||
{
|
||||
private:
|
||||
BOOST_TRIBOOL_THIRD_STATE(unspecified);
|
||||
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_keep_alive, keep_alive);
|
||||
|
||||
template <class Cond>
|
||||
struct Enabled : public std::integral_constant <bool, Cond::value>
|
||||
{
|
||||
};
|
||||
|
||||
static_assert (! std::is_const <Socket>::value,
|
||||
"Socket cannot be const");
|
||||
|
||||
typedef boost::system::error_code error_code;
|
||||
typedef boost::asio::streambuf write_buffers;
|
||||
typedef boost::basic_string_ref <
|
||||
char, ci_char_traits> ci_string_ref;
|
||||
|
||||
class abstract_request;
|
||||
class abstract_response;
|
||||
|
||||
Socket m_socket;
|
||||
boost::asio::io_service::strand m_strand;
|
||||
boost::asio::deadline_timer m_timer;
|
||||
|
||||
asio::shared_handler <void(error_code)> m_handler;
|
||||
std::unique_ptr <abstract_request> m_request;
|
||||
std::unique_ptr <abstract_response> m_response;
|
||||
|
||||
raw_parser m_parser;
|
||||
write_buffers m_write_buffer;
|
||||
boost::asio::mutable_buffer m_read_buffer;
|
||||
std::string m_field;
|
||||
std::string m_value;
|
||||
|
||||
bool m_complete : 1;
|
||||
bool m_keep_alive : 1;
|
||||
|
||||
public:
|
||||
typedef Socket stream_type;
|
||||
|
||||
client_session& operator= (client_session const&) = delete;
|
||||
|
||||
template <class... Args>
|
||||
explicit client_session (Args&&... args)
|
||||
: m_socket (std::forward <Args> (args)...)
|
||||
, m_strand (m_socket.get_io_service())
|
||||
, m_timer (m_socket.get_io_service())
|
||||
, m_parser (*this)
|
||||
{
|
||||
}
|
||||
|
||||
~client_session() = default;
|
||||
|
||||
/** Returns the stream associated with the session. */
|
||||
/** @{ */
|
||||
stream_type&
|
||||
stream()
|
||||
{
|
||||
return m_socket;
|
||||
}
|
||||
|
||||
stream_type const&
|
||||
stream() const
|
||||
{
|
||||
return m_socket;
|
||||
}
|
||||
/** @} */
|
||||
|
||||
void
|
||||
cancel()
|
||||
{
|
||||
error_code ec;
|
||||
m_socket.cancel(ec);
|
||||
}
|
||||
|
||||
/** Fetch a resource asynchronously. */
|
||||
template <
|
||||
class Request,
|
||||
class Response,
|
||||
class Handler
|
||||
>
|
||||
void
|
||||
async_get (Request request, Response response, Handler&& handler)
|
||||
{
|
||||
m_handler = std::forward <Handler> (handler);
|
||||
|
||||
m_request = std::make_unique <
|
||||
wrapped_request <Request>> (request);
|
||||
|
||||
m_response = std::make_unique <
|
||||
wrapped_response <Response>> (response);
|
||||
|
||||
start();
|
||||
}
|
||||
|
||||
template <
|
||||
class Handler
|
||||
>
|
||||
void
|
||||
async_get (std::string const&) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
class abstract_request
|
||||
{
|
||||
public:
|
||||
virtual
|
||||
~abstract_request()
|
||||
{
|
||||
}
|
||||
|
||||
virtual
|
||||
boost::tribool
|
||||
keep_alive () = 0;
|
||||
|
||||
virtual
|
||||
void
|
||||
headers (write_buffers& buffer) = 0;
|
||||
};
|
||||
|
||||
template <class Request>
|
||||
class wrapped_request : public abstract_request
|
||||
{
|
||||
private:
|
||||
typedef std::remove_reference_t <Request> request_type;
|
||||
|
||||
Request m_request;
|
||||
|
||||
public:
|
||||
explicit wrapped_request (Request request)
|
||||
: m_request (request)
|
||||
{
|
||||
}
|
||||
|
||||
wrapped_request (wrapped_request const&) = delete;
|
||||
|
||||
private:
|
||||
boost::tribool
|
||||
keep_alive() override
|
||||
{
|
||||
return keep_alive (Enabled <has_keep_alive <
|
||||
request_type, bool ()>>());
|
||||
}
|
||||
|
||||
boost::tribool
|
||||
keep_alive (std::true_type)
|
||||
{
|
||||
return m_request.keep_alive();
|
||||
}
|
||||
|
||||
boost::tribool
|
||||
keep_alive (std::false_type)
|
||||
{
|
||||
return unspecified;
|
||||
}
|
||||
|
||||
class submit
|
||||
{
|
||||
private:
|
||||
write_buffers& m_buffer;
|
||||
|
||||
public:
|
||||
explicit submit (write_buffers& buffer)
|
||||
: m_buffer (buffer)
|
||||
{
|
||||
}
|
||||
|
||||
// Throws if an invalid request field is specified.
|
||||
// Invalid fields are ones that the client_session inserts
|
||||
// itself, such as keep-alive.
|
||||
//
|
||||
static void check_request_field (std::string const& field)
|
||||
{
|
||||
static std::vector <std::string> reserved =
|
||||
{
|
||||
"Content-Length",
|
||||
"Connection"
|
||||
};
|
||||
|
||||
if (std::any_of (reserved.cbegin(), reserved.cend(),
|
||||
[&](typename decltype(reserved)::value_type const& s)
|
||||
{
|
||||
return detail::field_eq (field, s);
|
||||
}))
|
||||
throw std::invalid_argument (
|
||||
"Reserved HTTP header in request");
|
||||
}
|
||||
|
||||
template <class F, class V>
|
||||
void
|
||||
operator() (F const& f, V const& v)
|
||||
{
|
||||
check_request_field (f);
|
||||
|
||||
auto const fb (boost::asio::buffer (f));
|
||||
m_buffer.commit (boost::asio::buffer_copy (
|
||||
m_buffer.prepare (boost::asio::buffer_size (fb)), fb));
|
||||
m_buffer << ": ";
|
||||
auto const vb (boost::asio::buffer (v));
|
||||
m_buffer.commit (boost::asio::buffer_copy (
|
||||
m_buffer.prepare (boost::asio::buffer_size (vb)), vb));
|
||||
m_buffer << "\r\n";
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
headers (write_buffers& buffer) override
|
||||
{
|
||||
submit f (buffer);
|
||||
m_request.template headers <
|
||||
std::add_lvalue_reference_t <submit>> (f);
|
||||
}
|
||||
};
|
||||
|
||||
class abstract_response
|
||||
{
|
||||
public:
|
||||
abstract_response() = default;
|
||||
abstract_response (abstract_response const&) = default;
|
||||
abstract_response& operator= (abstract_response const&) = default;
|
||||
|
||||
virtual
|
||||
~abstract_response() = default;
|
||||
|
||||
virtual
|
||||
boost::asio::mutable_buffer
|
||||
buffer () = 0;
|
||||
|
||||
virtual
|
||||
error_code
|
||||
header (std::string const& field,
|
||||
std::string const& value) = 0;
|
||||
|
||||
virtual
|
||||
error_code
|
||||
body (boost::asio::const_buffer in) = 0;
|
||||
|
||||
};
|
||||
|
||||
template <class Response>
|
||||
class wrapped_response : public abstract_response
|
||||
{
|
||||
private:
|
||||
Response m_response;
|
||||
|
||||
public:
|
||||
explicit wrapped_response (Response response)
|
||||
: m_response (response)
|
||||
{
|
||||
}
|
||||
|
||||
wrapped_response (wrapped_response const&) = delete;
|
||||
|
||||
boost::asio::mutable_buffer
|
||||
buffer() override
|
||||
{
|
||||
return m_response.buffer();
|
||||
}
|
||||
|
||||
error_code
|
||||
header (std::string const& field,
|
||||
std::string const& value) override
|
||||
{
|
||||
return m_response.header (field, value);
|
||||
}
|
||||
|
||||
virtual
|
||||
error_code
|
||||
body (boost::asio::const_buffer in)
|
||||
{
|
||||
return m_response.body (in);
|
||||
}
|
||||
};
|
||||
|
||||
void upcall (error_code const& ec, bool continuation = true)
|
||||
{
|
||||
if (m_handler)
|
||||
{
|
||||
// TODO cancel all pending i/o here?
|
||||
|
||||
if (continuation)
|
||||
{
|
||||
m_handler (ec);
|
||||
m_handler = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_socket.get_io_service().post (
|
||||
asio::bind_handler (
|
||||
std::move (m_handler), ec));
|
||||
assert (! m_handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
// reset and setup state
|
||||
|
||||
m_parser.reset (raw_parser::response);
|
||||
|
||||
m_write_buffer.consume (m_write_buffer.size());
|
||||
m_write_buffer <<
|
||||
"GET / HTTP/1.0\r\n";
|
||||
m_request->headers (m_write_buffer);
|
||||
m_write_buffer <<
|
||||
"Content-Length: 0\r\n"
|
||||
"\r\n";
|
||||
|
||||
m_read_buffer = m_response->buffer();
|
||||
|
||||
m_field = std::string();
|
||||
m_value = std::string();
|
||||
|
||||
m_complete = false;
|
||||
m_keep_alive = false;
|
||||
|
||||
async_write_some (false);
|
||||
}
|
||||
|
||||
//
|
||||
// request
|
||||
//
|
||||
|
||||
bool
|
||||
async_write_some (bool continuation = true)
|
||||
{
|
||||
auto const& data (m_write_buffer.data());
|
||||
auto const size (boost::asio::buffer_size (
|
||||
m_write_buffer.data()));
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
m_socket.async_write_some (data, this->wrap_with_counter (
|
||||
m_strand.wrap (asio::wrap_handler (std::bind (
|
||||
&client_session::handle_write, this,
|
||||
asio::placeholders::error,
|
||||
asio::placeholders::bytes_transferred),
|
||||
continuation))));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
handle_write (error_code ec, std::size_t bytes_transferred)
|
||||
{
|
||||
if (ec)
|
||||
return upcall (ec);
|
||||
|
||||
m_write_buffer.consume (bytes_transferred);
|
||||
|
||||
if (async_write_some())
|
||||
return;
|
||||
|
||||
// write finished
|
||||
|
||||
//if (! keep_alive)
|
||||
{
|
||||
m_socket.shutdown (
|
||||
boost::asio::socket_base::shutdown_send, ec);
|
||||
// VFALCO What do we do with ec?
|
||||
}
|
||||
|
||||
// now read
|
||||
|
||||
async_read_some (true);
|
||||
}
|
||||
|
||||
//
|
||||
// response
|
||||
//
|
||||
|
||||
void
|
||||
async_read_some (bool continuation = true)
|
||||
{
|
||||
m_socket.async_read_some (boost::asio::mutable_buffers_1 (
|
||||
m_read_buffer), this->wrap_with_counter (
|
||||
m_strand.wrap (asio::wrap_handler (std::bind (
|
||||
&client_session::handle_read, this,
|
||||
asio::placeholders::error,
|
||||
asio::placeholders::bytes_transferred),
|
||||
continuation))));
|
||||
};
|
||||
|
||||
void
|
||||
handle_read (error_code ec, std::size_t bytes_transferred)
|
||||
{
|
||||
if (ec != boost::asio::error::eof)
|
||||
{
|
||||
if (ec)
|
||||
return upcall (ec);
|
||||
|
||||
std::size_t bytes_consumed;
|
||||
std::tie (ec, bytes_consumed) = m_parser.process_data (
|
||||
boost::asio::buffer_cast <void const*> (m_read_buffer),
|
||||
bytes_transferred);
|
||||
|
||||
// TODO Handle leftover bytes
|
||||
//assert (ec || bytes_consumed == bytes_transferred);
|
||||
|
||||
if (ec)
|
||||
return upcall (ec);
|
||||
|
||||
if (! m_complete)
|
||||
return async_read_some();
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is here for when we expect keep-alive but
|
||||
// the server ends up closing the connection erroneously.
|
||||
if (m_keep_alive)
|
||||
{
|
||||
m_keep_alive = false;
|
||||
// warning: Got EOF on keep-alive
|
||||
}
|
||||
|
||||
ec = m_parser.process_eof();
|
||||
}
|
||||
|
||||
if (! m_complete)
|
||||
{
|
||||
// custom error
|
||||
ec = error_code (boost::system::errc::no_message_available,
|
||||
boost::system::generic_category());
|
||||
}
|
||||
|
||||
if (ec)
|
||||
return upcall (ec);
|
||||
|
||||
// We have a complete response
|
||||
|
||||
if (! m_keep_alive)
|
||||
{
|
||||
// VFALCO NOTE This is surely wrong for ssl::stream
|
||||
{
|
||||
error_code ec_;
|
||||
m_socket.shutdown (
|
||||
boost::asio::socket_base::shutdown_receive, ec_);
|
||||
}
|
||||
|
||||
{
|
||||
error_code ec_;
|
||||
m_socket.close (ec_);
|
||||
assert (! ec_);
|
||||
}
|
||||
}
|
||||
|
||||
m_request.reset();
|
||||
m_response.reset();
|
||||
m_handler (ec);
|
||||
|
||||
// done
|
||||
}
|
||||
|
||||
//
|
||||
// parser
|
||||
//
|
||||
|
||||
error_code
|
||||
do_header()
|
||||
{
|
||||
error_code ec;
|
||||
|
||||
if (! m_value.empty())
|
||||
{
|
||||
ec = m_response->header (m_field, m_value);
|
||||
|
||||
m_field.clear();
|
||||
m_value.clear();
|
||||
}
|
||||
|
||||
return ec;
|
||||
}
|
||||
|
||||
error_code
|
||||
on_response () override
|
||||
{
|
||||
m_field = decltype(m_field)();
|
||||
m_value = decltype(m_value)();
|
||||
return error_code();
|
||||
}
|
||||
|
||||
error_code
|
||||
on_url (
|
||||
void const* in, std::size_t bytes) override
|
||||
{
|
||||
// Shouldn't be called for HTTP responses
|
||||
assert (false);
|
||||
return error_code();
|
||||
}
|
||||
|
||||
error_code
|
||||
on_status (int status_code,
|
||||
void const* in, std::size_t bytes) override
|
||||
{
|
||||
return error_code();
|
||||
}
|
||||
|
||||
error_code
|
||||
on_header_field (
|
||||
void const* in, std::size_t bytes) override
|
||||
{
|
||||
do_header();
|
||||
m_field.append (static_cast <char const*> (in), bytes);
|
||||
return error_code();
|
||||
}
|
||||
|
||||
error_code
|
||||
on_header_value (
|
||||
void const* in, std::size_t bytes) override
|
||||
{
|
||||
m_value.append (static_cast <char const*> (in), bytes);
|
||||
return error_code();
|
||||
}
|
||||
|
||||
error_code
|
||||
on_headers_done (
|
||||
bool keep_alive) override
|
||||
{
|
||||
do_header();
|
||||
|
||||
return error_code();
|
||||
}
|
||||
|
||||
error_code
|
||||
on_body (bool,
|
||||
void const* in, std::size_t bytes) override
|
||||
{
|
||||
m_response->body (
|
||||
boost::asio::const_buffer (in, bytes));
|
||||
return error_code();
|
||||
}
|
||||
|
||||
error_code
|
||||
on_message_complete (bool keep_alive) override
|
||||
{
|
||||
m_keep_alive = keep_alive;
|
||||
m_complete = true;
|
||||
return error_code();
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Synchronous HTTP client session. */
|
||||
template <class Socket>
|
||||
class sync_client_session
|
||||
{
|
||||
private:
|
||||
typedef boost::system::error_code error_code;
|
||||
|
||||
boost::asio::io_service m_ios;
|
||||
Socket m_socket;
|
||||
error_code m_ec;
|
||||
|
||||
static_assert (std::is_same <Socket, std::decay_t <Socket>>::value,
|
||||
"Socket cannot be a reference or const type");
|
||||
|
||||
struct sync_handler
|
||||
{
|
||||
std::reference_wrapper <sync_client_session> m_session;
|
||||
|
||||
sync_handler (sync_client_session& session)
|
||||
: m_session (session)
|
||||
{
|
||||
}
|
||||
|
||||
void operator() (boost::system::error_code ec)
|
||||
{
|
||||
m_session.get().m_ec = ec;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
typedef std::remove_reference_t <Socket> next_layer_type;
|
||||
typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
|
||||
|
||||
sync_client_session()
|
||||
: m_socket (m_ios)
|
||||
{
|
||||
}
|
||||
|
||||
sync_client_session (sync_client_session const&) = delete;
|
||||
|
||||
// VFALCO We might be able to get away with having move ctor/assign
|
||||
|
||||
~sync_client_session() = default;
|
||||
|
||||
next_layer_type&
|
||||
next_layer() noexcept
|
||||
{
|
||||
return m_socket;
|
||||
}
|
||||
|
||||
next_layer_type const&
|
||||
next_layer() const noexcept
|
||||
{
|
||||
}
|
||||
|
||||
lowest_layer_type&
|
||||
lowest_layer() noexcept
|
||||
{
|
||||
return m_socket.lowest_layer();
|
||||
}
|
||||
|
||||
lowest_layer_type const&
|
||||
lowest_layer() const noexcept
|
||||
{
|
||||
return m_socket.lowest_layer();
|
||||
}
|
||||
|
||||
template <class Request, class Response>
|
||||
error_code
|
||||
get (Request& request, Response& response)
|
||||
{
|
||||
client_session <Socket&> session (m_socket);
|
||||
session.template async_get <
|
||||
std::add_lvalue_reference_t <Request>,
|
||||
std::add_lvalue_reference_t <Response>,
|
||||
sync_handler> (
|
||||
request, response, sync_handler (*this));
|
||||
m_ios.run();
|
||||
m_ios.reset();
|
||||
return m_ec;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
63
beast/http/detail/header_traits.h
Normal file
63
beast/http/detail/header_traits.h
Normal file
@@ -0,0 +1,63 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_HTTP_HEADER_TRAITS_H_INCLUDED
|
||||
#define BEAST_HTTP_HEADER_TRAITS_H_INCLUDED
|
||||
|
||||
#include "../../utility/ci_char_traits.h"
|
||||
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
namespace detail {
|
||||
|
||||
// Utilities for dealing with HTTP headers
|
||||
|
||||
template <class Allocator = std::allocator <char>>
|
||||
using basic_field_string =
|
||||
std::basic_string <char, ci_char_traits, Allocator>;
|
||||
|
||||
typedef basic_field_string <> field_string;
|
||||
|
||||
typedef boost::basic_string_ref <char, ci_char_traits> field_string_ref;
|
||||
|
||||
/** Returns `true` if two header fields are the same.
|
||||
The comparison is case-insensitive.
|
||||
*/
|
||||
template <class Alloc1, class Alloc2>
|
||||
inline
|
||||
bool field_eq (
|
||||
std::basic_string <char, std::char_traits <char>, Alloc1> const& s1,
|
||||
std::basic_string <char, std::char_traits <char>, Alloc2> const& s2)
|
||||
{
|
||||
return field_string_ref (s1.c_str(), s1.size()) ==
|
||||
field_string_ref (s2.c_str(), s2.size());
|
||||
}
|
||||
|
||||
/** Returns the string with leading and trailing LWS removed. */
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
38
beast/http/get.h
Normal file
38
beast/http/get.h
Normal file
@@ -0,0 +1,38 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_HTTP_GET_H_INCLUDED
|
||||
#define BEAST_HTTP_GET_H_INCLUDED
|
||||
|
||||
#include <boost/system/error_code.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
/** Perform simple HTTP GET to retrieve a resource as a string. */
|
||||
std::pair <std::string, boost::system::error_code>
|
||||
get (std::string const& url_string);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
128
beast/http/impl/basic_url.cpp
Normal file
128
beast/http/impl/basic_url.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include "../basic_url.h"
|
||||
|
||||
#include "joyent_parser.h"
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
namespace detail {
|
||||
|
||||
void
|
||||
basic_url_base::parse_impl (string_ref s, boost::system::error_code& ec)
|
||||
{
|
||||
joyent::http_parser_url p;
|
||||
|
||||
value_type const* const data (s.data());
|
||||
|
||||
int const error (joyent::http_parser_parse_url (
|
||||
data, s.size(), false, &p));
|
||||
|
||||
if (error)
|
||||
{
|
||||
ec = boost::system::error_code (
|
||||
boost::system::errc::invalid_argument,
|
||||
boost::system::generic_category());
|
||||
return;
|
||||
}
|
||||
|
||||
if ((p.field_set & (1<<joyent::UF_SCHEMA)) != 0)
|
||||
{
|
||||
m_scheme = string_ref (
|
||||
data + p.field_data [joyent::UF_SCHEMA].off,
|
||||
p.field_data [joyent::UF_SCHEMA].len);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_scheme = string_ref {};
|
||||
}
|
||||
|
||||
if ((p.field_set & (1<<joyent::UF_HOST)) != 0)
|
||||
{
|
||||
m_host = string_ref (
|
||||
data + p.field_data [joyent::UF_HOST].off,
|
||||
p.field_data [joyent::UF_HOST].len);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_host = string_ref {};
|
||||
}
|
||||
|
||||
if ((p.field_set & (1<<joyent::UF_PORT)) != 0)
|
||||
{
|
||||
m_port = p.port;
|
||||
m_port_string = string_ref (
|
||||
data + p.field_data [joyent::UF_PORT].off,
|
||||
p.field_data [joyent::UF_PORT].len);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_port = 0;
|
||||
m_port_string = string_ref {};
|
||||
}
|
||||
|
||||
if ((p.field_set & (1<<joyent::UF_PATH)) != 0)
|
||||
{
|
||||
m_path = string_ref (
|
||||
data + p.field_data [joyent::UF_PATH].off,
|
||||
p.field_data [joyent::UF_PATH].len);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_path = string_ref {};
|
||||
}
|
||||
|
||||
if ((p.field_set & (1<<joyent::UF_QUERY)) != 0)
|
||||
{
|
||||
m_query = string_ref (
|
||||
data + p.field_data [joyent::UF_QUERY].off,
|
||||
p.field_data [joyent::UF_QUERY].len);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_query = string_ref {};
|
||||
}
|
||||
|
||||
if ((p.field_set & (1<<joyent::UF_FRAGMENT)) != 0)
|
||||
{
|
||||
m_fragment = string_ref (
|
||||
data + p.field_data [joyent::UF_FRAGMENT].off,
|
||||
p.field_data [joyent::UF_FRAGMENT].len);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_fragment = string_ref {};
|
||||
}
|
||||
|
||||
if ((p.field_set & (1<<joyent::UF_USERINFO)) != 0)
|
||||
{
|
||||
m_userinfo = string_ref (
|
||||
data + p.field_data [joyent::UF_USERINFO].off,
|
||||
p.field_data [joyent::UF_USERINFO].len);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_userinfo = string_ref {};
|
||||
}
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // http
|
||||
} // beast
|
||||
42
beast/http/impl/get.cpp
Normal file
42
beast/http/impl/get.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include "../get.h"
|
||||
|
||||
#include "../basic_url.h"
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
std::pair <std::string, boost::system::error_code>
|
||||
get (std::string const& url_string)
|
||||
{
|
||||
std::pair <std::string, boost::system::error_code> result;
|
||||
|
||||
url u;
|
||||
u.parse (url_string, result.second);
|
||||
if (result.second)
|
||||
return result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,8 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include "joyent_parser.h"
|
||||
|
||||
#include "../basic_message.h"
|
||||
|
||||
#include <boost/system/error_code.hpp>
|
||||
|
||||
45
beast/http/tests/basic_message.test.cpp
Normal file
45
beast/http/tests/basic_message.test.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#if BEAST_INCLUDE_BEASTCONFIG
|
||||
#include "../../BeastConfig.h"
|
||||
#endif
|
||||
|
||||
#include "../../unit_test/suite.h"
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
class basic_message_tests : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
void testCreate()
|
||||
{
|
||||
pass();
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
testCreate();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(basic_message,http,beast);
|
||||
}
|
||||
}
|
||||
56
beast/http/tests/basic_url.test.cpp
Normal file
56
beast/http/tests/basic_url.test.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include "../basic_url.h"
|
||||
|
||||
#include "../../unit_test/suite.h"
|
||||
|
||||
namespace beast {
|
||||
|
||||
class basic_url_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
void
|
||||
run ()
|
||||
{
|
||||
std::vector <char const*> const urls {
|
||||
"http://www.example.com/#%c2%a9",
|
||||
"http://127.0.0.1:443",
|
||||
"http://192.168.0.1 hello.urltest.lookout.net/",
|
||||
"http://\\uff10\\uff38\\uff43\\uff10\\uff0e\\uff10\\uff12\\uff15\\uff10\\uff0e\\uff10\\uff11.urltest.lookout.net/"
|
||||
};
|
||||
http::url url;
|
||||
for (auto const& s : urls)
|
||||
{
|
||||
try
|
||||
{
|
||||
url.parse (s);
|
||||
pass();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE_MANUAL(basic_url,http,beast);
|
||||
|
||||
}
|
||||
383
beast/http/tests/client_session.test.cpp
Normal file
383
beast/http/tests/client_session.test.cpp
Normal file
@@ -0,0 +1,383 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
// LIBS: pthread
|
||||
// MODULES: urls_large_data.cpp ../impl/raw_parser.cpp ../impl/joyent_parser.cpp
|
||||
|
||||
#if BEAST_INCLUDE_BEASTCONFIG
|
||||
#include "../../BeastConfig.h"
|
||||
#endif
|
||||
|
||||
#include "../../unit_test/suite.h"
|
||||
|
||||
#include "urls_large_data.h"
|
||||
#include "../client_session.h"
|
||||
#include "../get.h"
|
||||
#include "../../asio/bind_handler.h"
|
||||
#include "../../asio/memory_buffer.h"
|
||||
#include "../../utility/ci_char_traits.h"
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
/** Allows thread-safe forward traversal of a sequence.
|
||||
|
||||
Each time the shared_iterator is dereferenced it provides an element in
|
||||
the sequence or the one-past-the-end iterator if there are no elements
|
||||
remaining in the sequence. Access to the shared iterator is thread safe:
|
||||
multiple threads of execution can request iterators from the sequence,
|
||||
and no two threads will see the same iterator.
|
||||
|
||||
Any operations on the underlying container which would invalidate
|
||||
iterators or change the sequence of elements pointed to by the range
|
||||
of iterators referenced by the shared_iterator, results in undefined
|
||||
behavior.
|
||||
*/
|
||||
template <class Iterator>
|
||||
class shared_iterator
|
||||
{
|
||||
public:
|
||||
static_assert (std::is_same <Iterator, std::decay_t <Iterator>>::value,
|
||||
"Iterator may not be a reference or const type");
|
||||
|
||||
typedef Iterator value_type;
|
||||
|
||||
private:
|
||||
std::mutex m_mutex;
|
||||
Iterator m_iter;
|
||||
Iterator m_end;
|
||||
|
||||
public:
|
||||
/** Construct the iteration from the range [first, last) */
|
||||
shared_iterator (Iterator first, Iterator last)
|
||||
: m_iter (first)
|
||||
, m_end (last)
|
||||
{
|
||||
}
|
||||
|
||||
/** Obtains the next iterator in the sequence.
|
||||
Post-condition
|
||||
Current shared position in the sequence is advanced by one.
|
||||
Thread safety:
|
||||
Can be called from any thread at any time.
|
||||
*/
|
||||
Iterator
|
||||
operator* ()
|
||||
{
|
||||
std::lock_guard <decltype(m_mutex)> lock (m_mutex);
|
||||
if (m_iter == m_end)
|
||||
return m_iter;
|
||||
return m_iter++;
|
||||
}
|
||||
|
||||
/** Returns the one-past-the end iterator for the sequence.
|
||||
Thread safety:
|
||||
Can be called from any thread at any time.
|
||||
*/
|
||||
Iterator
|
||||
end() const
|
||||
{
|
||||
return m_end;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class client_session_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
typedef boost::system::error_code error_code;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** Used to submit HTTP requests. */
|
||||
class Request
|
||||
{
|
||||
private:
|
||||
typedef std::string value_type;
|
||||
typedef std::string string_type;
|
||||
|
||||
std::unordered_map <std::string, string_type> m_headers;
|
||||
|
||||
// This also works, for allowing header values to
|
||||
// span multiple discontiguous memory buffers.
|
||||
//
|
||||
std::unordered_map <std::string,
|
||||
std::vector <std::string>> m_headers_plus;
|
||||
|
||||
class vector_proxy
|
||||
{
|
||||
private:
|
||||
std::reference_wrapper <std::vector <string_type>> m_vec;
|
||||
|
||||
public:
|
||||
explicit vector_proxy (std::vector <string_type>& vec)
|
||||
: m_vec (vec)
|
||||
{
|
||||
}
|
||||
|
||||
vector_proxy& operator= (string_type const& s)
|
||||
{
|
||||
m_vec.get().emplace_back (s);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
bool keep_alive()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Use this to set the fields
|
||||
std::string&
|
||||
operator[] (std::string const& field)
|
||||
{
|
||||
return m_headers[field];
|
||||
}
|
||||
|
||||
/** Calls Function for each header.
|
||||
|
||||
Requirements:
|
||||
|
||||
`X` The type `Function`
|
||||
`Y` A type meeting this requirement:
|
||||
ConvertibleToConstBuffer
|
||||
`Z` A type meeting either requirement:
|
||||
ConstBufferSequence
|
||||
ConvertibleToConstBuffer
|
||||
`f` A value of type `X`
|
||||
`n` A value of type `Y`
|
||||
`v` A value of type `Z`
|
||||
|
||||
The expression
|
||||
|
||||
f (n, v);
|
||||
|
||||
must be well formed.
|
||||
*/
|
||||
template <class Function>
|
||||
void
|
||||
headers (Function f)
|
||||
{
|
||||
for (auto const& h : m_headers)
|
||||
f (h.first, h.second);
|
||||
}
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
class Response
|
||||
{
|
||||
private:
|
||||
typedef boost::system::error_code error_code;
|
||||
asio::memory_buffer <std::uint8_t> m_buffer;
|
||||
boost::asio::streambuf m_body;
|
||||
|
||||
public:
|
||||
enum
|
||||
{
|
||||
buffer_bytes = 4192
|
||||
};
|
||||
|
||||
typedef std::vector <std::pair <
|
||||
std::string, std::string>> headers_type;
|
||||
|
||||
headers_type headers;
|
||||
|
||||
Response()
|
||||
: m_buffer (buffer_bytes)
|
||||
{
|
||||
}
|
||||
|
||||
boost::asio::mutable_buffer
|
||||
buffer()
|
||||
{
|
||||
return boost::asio::mutable_buffer (
|
||||
m_buffer.data(), m_buffer.size());
|
||||
}
|
||||
|
||||
template <class FieldString, class ValueString>
|
||||
error_code
|
||||
header (FieldString const& field, ValueString const& value)
|
||||
{
|
||||
headers.push_back (std::make_pair (field, value));
|
||||
return error_code();
|
||||
}
|
||||
|
||||
error_code
|
||||
body (boost::asio::const_buffer in)
|
||||
{
|
||||
m_body.commit (boost::asio::buffer_copy (
|
||||
m_body.prepare (boost::asio::buffer_size (in)),
|
||||
boost::asio::buffer (in)));
|
||||
return error_code();
|
||||
}
|
||||
|
||||
std::size_t
|
||||
size() const
|
||||
{
|
||||
return m_body.size();
|
||||
}
|
||||
|
||||
std::string
|
||||
data() const
|
||||
{
|
||||
std::string s;
|
||||
s.resize (m_body.size());
|
||||
boost::asio::buffer_copy (boost::asio::buffer (
|
||||
&s[0], s.size()), m_body.data());
|
||||
return s;
|
||||
}
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
template <class Session>
|
||||
error_code
|
||||
visit (Session& session, std::string const& url)
|
||||
{
|
||||
error_code ec;
|
||||
typedef boost::asio::ip::tcp::resolver resolver_t;
|
||||
boost::asio::io_service ios;
|
||||
resolver_t r (ios);
|
||||
auto iter (r.resolve (resolver_t::query (
|
||||
url, "80", resolver_t::query::numeric_service), ec));
|
||||
|
||||
if (ec)
|
||||
return ec;
|
||||
|
||||
if (iter != resolver_t::iterator())
|
||||
{
|
||||
session.next_layer().connect (iter->endpoint(), ec);
|
||||
if (ec)
|
||||
return ec;
|
||||
|
||||
Request req;
|
||||
req ["User-Agent"] = "rippled-http-client/1.0";
|
||||
req ["Host"] = url + ":80";
|
||||
req ["Content-Type"] = "application/text";
|
||||
req ["Accept"] = "application/text";
|
||||
|
||||
//req ["Content-length"] = "0";
|
||||
//req.prepare ("GET / HTTP/1.0");
|
||||
|
||||
Response resp;
|
||||
ec = session.get (req, resp);
|
||||
|
||||
if (ec)
|
||||
{
|
||||
// hack
|
||||
session.next_layer().close();
|
||||
}
|
||||
|
||||
log <<
|
||||
"GET " << url << " " << ec.message();
|
||||
|
||||
for (auto const& h : resp.headers)
|
||||
log << h.first << ": " << h.second;
|
||||
|
||||
log << resp.data();
|
||||
log << " ";
|
||||
}
|
||||
|
||||
return ec;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
template <class Iterator>
|
||||
void
|
||||
concurrent_get (shared_iterator <Iterator>& iter)
|
||||
{
|
||||
typedef boost::asio::ip::tcp::socket socket_type;
|
||||
for (auto cur (*iter); cur != iter.end(); cur = *iter)
|
||||
{
|
||||
sync_client_session <socket_type> session;
|
||||
std::string const base (*cur);
|
||||
std::string url;
|
||||
url = "www." + base;
|
||||
auto const ec (visit (session, url));
|
||||
}
|
||||
}
|
||||
|
||||
// Perform HTTP get on a sequence of URLs in parallel
|
||||
// Requirements
|
||||
// Sequence must me
|
||||
// Sequence::value_type must be convertible to std::string
|
||||
template <class Iterator>
|
||||
void test_concurrent_get (Iterator first, Iterator last)
|
||||
{
|
||||
#if 0
|
||||
last = first;
|
||||
std::advance (last, 3000);
|
||||
#endif
|
||||
|
||||
shared_iterator <Iterator> iter (first, last);
|
||||
|
||||
std::vector <std::thread> pool;
|
||||
#if 0
|
||||
std::size_t const hardware_concurrency (
|
||||
std::max (std::thread::hardware_concurrency(),
|
||||
2u
|
||||
));
|
||||
#else
|
||||
std::size_t const hardware_concurrency (1);
|
||||
#endif
|
||||
|
||||
for (std::size_t n (hardware_concurrency); n--;)
|
||||
pool.emplace_back (std::bind (
|
||||
&client_session_test::concurrent_get <Iterator>, this,
|
||||
std::ref (iter)));
|
||||
|
||||
for (auto& t : pool)
|
||||
t.join();
|
||||
|
||||
pass();
|
||||
}
|
||||
|
||||
template <class Sequence>
|
||||
void test_concurrent_get (Sequence const& sequence)
|
||||
{
|
||||
auto last (std::begin(sequence));
|
||||
std::advance (last, std::min (std::size_t(1), sequence.size()));
|
||||
test_concurrent_get (std::begin (sequence), last);
|
||||
}
|
||||
|
||||
void test_get()
|
||||
{
|
||||
get ("http://www.google.com");
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
//test_get();
|
||||
test_concurrent_get (urls_large_data());
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE_MANUAL(client_session,http,beast);
|
||||
|
||||
}
|
||||
}
|
||||
10038
beast/http/tests/urls_large_data.cpp
Normal file
10038
beast/http/tests/urls_large_data.cpp
Normal file
File diff suppressed because it is too large
Load Diff
34
beast/http/tests/urls_large_data.h
Normal file
34
beast/http/tests/urls_large_data.h
Normal file
@@ -0,0 +1,34 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_HTTP_URLS_LARGE_DATA_H_INCLUDED
|
||||
#define BEAST_HTTP_URLS_LARGE_DATA_H_INCLUDED
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
std::vector <char const*> const&
|
||||
urls_large_data();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user