mirror of
https://github.com/boostorg/beast.git
synced 2025-07-31 21:34:46 +02:00
Minimalistic method examples.
This commit is contained in:
committed by
Klemens Morgenstern
parent
51a73f2e64
commit
1841a592d6
@@ -51,7 +51,9 @@ used to evaluate robustness. All asynchronous clients support timeouts.
|
||||
][
|
||||
[HTTP json_body (synchronous)]
|
||||
[[path_link example/http/client/body/json_body.hpp example/http/client/body/json_client.cpp]]
|
||||
|
||||
][
|
||||
[HTTP client for all methods (synchronous)]
|
||||
[[path_link example/http/client/methods/http_client_methods.hpp example/http/client/methods/http_client_methods.cpp]]
|
||||
]]
|
||||
|
||||
These WebSocket clients connect to a
|
||||
|
@@ -13,6 +13,7 @@ add_subdirectory (coro)
|
||||
add_subdirectory (crawl)
|
||||
add_subdirectory (sync)
|
||||
add_subdirectory (body)
|
||||
add_subdirectory (methods)
|
||||
|
||||
if (OPENSSL_FOUND)
|
||||
add_subdirectory (async-ssl)
|
||||
@@ -21,3 +22,4 @@ if (OPENSSL_FOUND)
|
||||
add_subdirectory (coro-ssl)
|
||||
add_subdirectory (sync-ssl)
|
||||
endif()
|
||||
|
||||
|
@@ -20,3 +20,5 @@ build-project coro-ssl ;
|
||||
build-project sync-ssl ;
|
||||
|
||||
build-project body ;
|
||||
|
||||
build-project methods ;
|
||||
|
23
example/http/client/methods/CMakeLists.txt
Normal file
23
example/http/client/methods/CMakeLists.txt
Normal file
@@ -0,0 +1,23 @@
|
||||
#
|
||||
# Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
# Official repository: https://github.com/boostorg/beast
|
||||
#
|
||||
|
||||
GroupSources(include/boost/beast beast)
|
||||
GroupSources(example/http/client/methods "/")
|
||||
|
||||
add_executable (http-client-methods
|
||||
${BOOST_BEAST_FILES}
|
||||
Jamfile
|
||||
http_client_methods.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(http-client-methods
|
||||
lib-asio
|
||||
lib-beast)
|
||||
|
||||
set_property(TARGET http-client-methods PROPERTY FOLDER "example-http-client-methods")
|
15
example/http/client/methods/Jamfile
Normal file
15
example/http/client/methods/Jamfile
Normal file
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
# Official repository: https://github.com/boostorg/beast
|
||||
#
|
||||
|
||||
exe http-client-methods :
|
||||
http_client_methods.cpp
|
||||
:
|
||||
<variant>coverage:<build>no
|
||||
<variant>ubasan:<build>no
|
||||
;
|
225
example/http/client/methods/http_client_methods.cpp
Normal file
225
example/http/client/methods/http_client_methods.cpp
Normal file
@@ -0,0 +1,225 @@
|
||||
//
|
||||
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/beast
|
||||
//
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Example: HTTP client, synchronous for every method on httpbin
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//[example_http_client_methods
|
||||
|
||||
#include <boost/beast/core.hpp>
|
||||
#include <boost/beast/http.hpp>
|
||||
#include <boost/beast/version.hpp>
|
||||
#include <boost/asio/connect.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
namespace beast = boost::beast; // from <boost/beast.hpp>
|
||||
namespace http = beast::http; // from <boost/beast/http.hpp>
|
||||
namespace net = boost::asio; // from <boost/asio.hpp>
|
||||
using tcp = net::ip::tcp; // from <boost/asio/ip/tcp.hpp>
|
||||
|
||||
|
||||
// perform a get request
|
||||
void do_get(beast::tcp_stream & stream,
|
||||
http::request<http::string_body> & req,
|
||||
beast::flat_buffer buffer,
|
||||
http::response<http::dynamic_body> & res)
|
||||
{
|
||||
req.target("/get");
|
||||
req.method(beast::http::verb::get);
|
||||
http::write(stream, req);
|
||||
http::read(stream, buffer, res);
|
||||
}
|
||||
|
||||
// perform a head request
|
||||
void do_head(beast::tcp_stream & stream,
|
||||
http::request<http::string_body> & req,
|
||||
beast::flat_buffer buffer,
|
||||
http::response<http::dynamic_body> & res)
|
||||
{
|
||||
// we reuse the get endpoint
|
||||
req.target("/get");
|
||||
req.method(beast::http::verb::head);
|
||||
http::write(stream, req);
|
||||
|
||||
/* the head response will send back a content-length
|
||||
* without a body. The other requests don't set content-length when not
|
||||
* sending a body back.
|
||||
*
|
||||
* the response parser doesn't know that we sent head,
|
||||
* so we need to manually make sure we're only reading the header
|
||||
* otherwise we're waiting forever for data.
|
||||
*/
|
||||
|
||||
http::response_parser<http::dynamic_body> p;
|
||||
http::read_header(stream, buffer, p);
|
||||
// move the result over
|
||||
res = p.release();
|
||||
}
|
||||
|
||||
|
||||
// perform a patch request
|
||||
void do_patch(beast::tcp_stream & stream,
|
||||
http::request<http::string_body> & req,
|
||||
beast::flat_buffer buffer,
|
||||
http::response<http::dynamic_body> & res)
|
||||
{
|
||||
req.target("/patch");
|
||||
req.method(beast::http::verb::patch);
|
||||
req.body() = "Some random patch data";
|
||||
req.prepare_payload(); // set content-length based on the body
|
||||
http::write(stream, req);
|
||||
http::read(stream, buffer, res);
|
||||
}
|
||||
|
||||
|
||||
// perform a put request
|
||||
void do_put(beast::tcp_stream & stream,
|
||||
http::request<http::string_body> & req,
|
||||
beast::flat_buffer buffer,
|
||||
http::response<http::dynamic_body> & res)
|
||||
{
|
||||
req.target("/put");
|
||||
req.method(beast::http::verb::put);
|
||||
req.body() = "Some random put data";
|
||||
req.prepare_payload(); // set content-length based on the body
|
||||
http::write(stream, req);
|
||||
http::read(stream, buffer, res);
|
||||
}
|
||||
|
||||
// perform a post request
|
||||
void do_post(beast::tcp_stream & stream,
|
||||
http::request<http::string_body> & req,
|
||||
beast::flat_buffer buffer,
|
||||
http::response<http::dynamic_body> & res)
|
||||
{
|
||||
req.target("/post");
|
||||
req.method(beast::http::verb::post);
|
||||
req.body() = "Some random post data";
|
||||
req.prepare_payload(); // set content-length based on the body
|
||||
http::write(stream, req);
|
||||
http::read(stream, buffer, res);
|
||||
}
|
||||
|
||||
|
||||
// perform a delete request
|
||||
void do_delete(beast::tcp_stream & stream,
|
||||
http::request<http::string_body> & req,
|
||||
beast::flat_buffer buffer,
|
||||
http::response<http::dynamic_body> & res)
|
||||
{
|
||||
req.target("/delete");
|
||||
req.method(beast::http::verb::delete_);
|
||||
// NOTE: delete doesn't require a body
|
||||
req.body() = "Some random delete data";
|
||||
req.prepare_payload(); // set content-length based on the body
|
||||
http::write(stream, req);
|
||||
http::read(stream, buffer, res);
|
||||
}
|
||||
|
||||
|
||||
// Performs an HTTP request against httpbin.cpp.al and prints request & response
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Check command line arguments.
|
||||
if(argc != 2)
|
||||
{
|
||||
std::cerr <<
|
||||
"Usage: http-client-method <method> \n" <<
|
||||
"Example:\n" <<
|
||||
" http-client-method get\n" <<
|
||||
" http-client-method post\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
for (char * c = argv[1]; *c != '\0'; c++)
|
||||
*c = static_cast<char>(std::tolower(*c));
|
||||
beast::string_view method{argv[1]};
|
||||
|
||||
// The io_context is required for all I/O
|
||||
net::io_context ioc;
|
||||
|
||||
// These objects perform our I/O
|
||||
tcp::resolver resolver(ioc);
|
||||
beast::tcp_stream stream(ioc);
|
||||
|
||||
// Look up the domain name
|
||||
auto const results = resolver.resolve("httpbin.cpp.al", "http");
|
||||
|
||||
// Make the connection on the IP address we get from a lookup
|
||||
stream.connect(results);
|
||||
|
||||
|
||||
// Set up an HTTP GET request message
|
||||
http::request<http::string_body> req;
|
||||
req.set(http::field::host, "httpbin.cpp.al");
|
||||
req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
|
||||
|
||||
|
||||
// This buffer is used for reading and must be persisted
|
||||
beast::flat_buffer buffer;
|
||||
|
||||
// Declare a container to hold the response
|
||||
http::response<http::dynamic_body> res;
|
||||
|
||||
if (method == "get")
|
||||
do_get(stream, req, buffer, res);
|
||||
else if (method == "head")
|
||||
do_head(stream, req, buffer, res);
|
||||
else if (method == "patch")
|
||||
do_patch(stream, req, buffer, res);
|
||||
else if (method == "put")
|
||||
do_put(stream, req, buffer, res);
|
||||
else if (method == "post")
|
||||
do_post(stream, req, buffer, res);
|
||||
else if (method == "delete")
|
||||
do_delete(stream, req, buffer, res);
|
||||
else
|
||||
{
|
||||
std::cerr << "Unknown method: " << method << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Write the message to standard out
|
||||
std::cout << "Request send:\n-----------------------------\n"
|
||||
<< req << std::endl;
|
||||
|
||||
|
||||
// Write the message to standard out
|
||||
std::cout << "\n\nResponse received:\n-----------------------------\n"
|
||||
<< res << std::endl;
|
||||
|
||||
// Gracefully close the socket
|
||||
beast::error_code ec;
|
||||
stream.socket().shutdown(tcp::socket::shutdown_both, ec);
|
||||
|
||||
// not_connected happens sometimes
|
||||
// so don't bother reporting it.
|
||||
//
|
||||
if(ec && ec != beast::errc::not_connected)
|
||||
throw beast::system_error{ec};
|
||||
|
||||
// If we get here then the connection is closed gracefully
|
||||
}
|
||||
catch(std::exception const& e)
|
||||
{
|
||||
std::cerr << "Error: " << e.what() << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
//]
|
Reference in New Issue
Block a user