mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-27 06:25: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" />
|
<None Include="..\..\scripts\compile.sh" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\BeastConfig.h" />
|
|
||||||
<ClInclude Include="..\..\beast\Arithmetic.h" />
|
<ClInclude Include="..\..\beast\Arithmetic.h" />
|
||||||
<ClInclude Include="..\..\beast\asio\abstract_socket.h" />
|
<ClInclude Include="..\..\beast\asio\abstract_socket.h" />
|
||||||
<ClInclude Include="..\..\beast\asio\bind_handler.h" />
|
<ClInclude Include="..\..\beast\asio\bind_handler.h" />
|
||||||
@@ -150,10 +149,15 @@
|
|||||||
<ClInclude Include="..\..\beast\cxx14\utility.h" />
|
<ClInclude Include="..\..\beast\cxx14\utility.h" />
|
||||||
<ClInclude Include="..\..\beast\HeapBlock.h" />
|
<ClInclude Include="..\..\beast\HeapBlock.h" />
|
||||||
<ClInclude Include="..\..\beast\http\basic_message.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\http-parser\http_parser.h" />
|
||||||
<ClInclude Include="..\..\beast\http\impl\joyent_parser.h" />
|
<ClInclude Include="..\..\beast\http\impl\joyent_parser.h" />
|
||||||
<ClInclude Include="..\..\beast\http\ParsedURL.h" />
|
<ClInclude Include="..\..\beast\http\ParsedURL.h" />
|
||||||
<ClInclude Include="..\..\beast\http\raw_parser.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\http\URL.h" />
|
||||||
<ClInclude Include="..\..\beast\Insight.h" />
|
<ClInclude Include="..\..\beast\Insight.h" />
|
||||||
<ClInclude Include="..\..\beast\insight\Base.h" />
|
<ClInclude Include="..\..\beast\insight\Base.h" />
|
||||||
@@ -257,6 +261,7 @@
|
|||||||
<ClInclude Include="..\..\beast\utility\type_name.h" />
|
<ClInclude Include="..\..\beast\utility\type_name.h" />
|
||||||
<ClInclude Include="..\..\beast\utility\zero.h" />
|
<ClInclude Include="..\..\beast\utility\zero.h" />
|
||||||
<ClInclude Include="..\..\beast\Version.h" />
|
<ClInclude Include="..\..\beast\Version.h" />
|
||||||
|
<ClInclude Include="..\..\BeastConfig.h" />
|
||||||
<ClInclude Include="..\..\modules\beast_asio\async\AsyncObject.h" />
|
<ClInclude Include="..\..\modules\beast_asio\async\AsyncObject.h" />
|
||||||
<ClInclude Include="..\..\modules\beast_asio\basics\FixedInputBuffer.h" />
|
<ClInclude Include="..\..\modules\beast_asio\basics\FixedInputBuffer.h" />
|
||||||
<ClInclude Include="..\..\modules\beast_asio\basics\PeerRole.h" />
|
<ClInclude Include="..\..\modules\beast_asio\basics\PeerRole.h" />
|
||||||
@@ -525,6 +530,18 @@
|
|||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\beast\http\HTTP.unity.cpp" />
|
<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">
|
<ClCompile Include="..\..\beast\http\impl\raw_parser.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|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)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</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)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
|
|||||||
@@ -274,6 +274,12 @@
|
|||||||
<Filter Include="beast\streams">
|
<Filter Include="beast\streams">
|
||||||
<UniqueIdentifier>{899ea9a6-1969-4cde-b26d-8ad60acebfa4}</UniqueIdentifier>
|
<UniqueIdentifier>{899ea9a6-1969-4cde-b26d-8ad60acebfa4}</UniqueIdentifier>
|
||||||
</Filter>
|
</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">
|
<Filter Include="beast\utility\tests">
|
||||||
<UniqueIdentifier>{3c58ba5e-1855-4865-8a9f-c0afd5014e74}</UniqueIdentifier>
|
<UniqueIdentifier>{3c58ba5e-1855-4865-8a9f-c0afd5014e74}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
@@ -1114,11 +1120,14 @@
|
|||||||
<ClInclude Include="..\..\beast\streams\abstract_ostream.h">
|
<ClInclude Include="..\..\beast\streams\abstract_ostream.h">
|
||||||
<Filter>beast\streams</Filter>
|
<Filter>beast\streams</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\beast\streams\basic_abstract_ostream.h">
|
<ClInclude Include="..\..\beast\http\client_session.h">
|
||||||
<Filter>beast\streams</Filter>
|
<Filter>beast\http</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\beast\streams\basic_scoped_ostream.h">
|
<ClInclude Include="..\..\beast\http\tests\urls_large_data.h">
|
||||||
<Filter>beast\streams</Filter>
|
<Filter>beast\http\tests</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\beast\http\detail\header_traits.h">
|
||||||
|
<Filter>beast\http\detail</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\beast\utility\maybe_const.h">
|
<ClInclude Include="..\..\beast\utility\maybe_const.h">
|
||||||
<Filter>beast\utility</Filter>
|
<Filter>beast\utility</Filter>
|
||||||
@@ -1210,6 +1219,18 @@
|
|||||||
<ClInclude Include="..\..\beast\utility\ci_char_traits.h">
|
<ClInclude Include="..\..\beast\utility\ci_char_traits.h">
|
||||||
<Filter>beast\utility</Filter>
|
<Filter>beast\utility</Filter>
|
||||||
</ClInclude>
|
</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>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\modules\beast_core\files\DirectoryIterator.cpp">
|
<ClCompile Include="..\..\modules\beast_core\files\DirectoryIterator.cpp">
|
||||||
@@ -1446,9 +1467,6 @@
|
|||||||
<ClCompile Include="..\..\beast\http\impl\URL.cpp">
|
<ClCompile Include="..\..\beast\http\impl\URL.cpp">
|
||||||
<Filter>beast\http\impl</Filter>
|
<Filter>beast\http\impl</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\beast\http\impl\ParsedURL.cpp">
|
|
||||||
<Filter>beast\http\impl</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\beast\crypto\impl\sha2\sha2.c">
|
<ClCompile Include="..\..\beast\crypto\impl\sha2\sha2.c">
|
||||||
<Filter>beast\crypto\impl\sha2</Filter>
|
<Filter>beast\crypto\impl\sha2</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@@ -1593,15 +1611,21 @@
|
|||||||
<ClCompile Include="..\..\beast\chrono\impl\chrono_io.cpp">
|
<ClCompile Include="..\..\beast\chrono\impl\chrono_io.cpp">
|
||||||
<Filter>beast\chrono\impl</Filter>
|
<Filter>beast\chrono\impl</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\beast\http\tests\ParsedURL.test.cpp">
|
|
||||||
<Filter>beast\http\tests</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\beast\net\tests\IPEndpoint.test.cpp">
|
<ClCompile Include="..\..\beast\net\tests\IPEndpoint.test.cpp">
|
||||||
<Filter>beast\net\tests</Filter>
|
<Filter>beast\net\tests</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\beast\streams\tests\basic_abstract_ostream.test.cpp">
|
<ClCompile Include="..\..\beast\streams\tests\basic_abstract_ostream.test.cpp">
|
||||||
<Filter>beast\streams\tests</Filter>
|
<Filter>beast\streams\tests</Filter>
|
||||||
</ClCompile>
|
</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">
|
<ClCompile Include="..\..\beast\threads\tests\Atomic.test.cpp">
|
||||||
<Filter>beast\threads\tests</Filter>
|
<Filter>beast\threads\tests</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@@ -1674,6 +1698,21 @@
|
|||||||
<ClCompile Include="..\..\modules\beast_sqlite\beast_sqlite.unity.c">
|
<ClCompile Include="..\..\modules\beast_sqlite\beast_sqlite.unity.c">
|
||||||
<Filter>beast_sqlite</Filter>
|
<Filter>beast_sqlite</Filter>
|
||||||
</ClCompile>
|
</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>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Text Include="..\..\TODO.txt">
|
<Text Include="..\..\TODO.txt">
|
||||||
|
|||||||
@@ -21,9 +21,14 @@
|
|||||||
#include "../../BeastConfig.h"
|
#include "../../BeastConfig.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "impl/URL.cpp"
|
#include "impl/basic_url.cpp"
|
||||||
#include "impl/ParsedURL.cpp"
|
#include "impl/get.cpp"
|
||||||
#include "impl/joyent_parser.cpp"
|
#include "impl/joyent_parser.cpp"
|
||||||
|
#include "impl/ParsedURL.cpp"
|
||||||
#include "impl/raw_parser.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/ParsedURL.cpp"
|
||||||
|
#include "tests/urls_large_data.cpp"
|
||||||
|
|||||||
@@ -17,8 +17,8 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#ifndef BEAST_ASIO_HTTP_BASIC_MESSAGE_H_INCLUDED
|
#ifndef BEAST_HTTP_BASIC_MESSAGE_H_INCLUDED
|
||||||
#define BEAST_ASIO_HTTP_BASIC_MESSAGE_H_INCLUDED
|
#define BEAST_HTTP_BASIC_MESSAGE_H_INCLUDED
|
||||||
|
|
||||||
#include <memory>
|
#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 "../basic_message.h"
|
||||||
|
|
||||||
#include <boost/system/error_code.hpp>
|
#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