Я изучаю библиотеку Boost.Beast. Я пытаюсь сделать запрос, ответ которого:
HTTP/1.1 301 Moved Permanently
Cache-Control: public
Content-Type: text/html; charset=UTF-8
Location: https://www.example.com/target/xxx/
Затем я пытаюсь сделать запрос с этим полем местоположения, но я получаю неправильный ответ на запрос.
Как я могу сделать перенаправление? Есть ли пример?
Это мой код:
boost::asio::io_service ios;
tcp::resolver resolver{ios};
tcp::socket socket{ios};
auto const lookup = resolver.resolve( tcp::resolver::query(host, port) );
boost::asio::connect(socket, lookup);
// Set up an HTTP GET request message
http::request<http::string_body> req{http::verb::get, target, 11};
req.set(http::field::host, host);
req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
// Send the HTTP request to the remote host
http::write(socket, req);
// This buffer is used for reading and must be persisted
boost::beast::flat_buffer buffer;
// Declare a container to hold the response
http::response<http::dynamic_body> res;
// Receive the HTTP response
http::read(socket, buffer, res);
if( res.base().result_int() == 301 ) {
req.set(http::field::location, res.base()["Location"]);
http::write(socket, req);
boost::beast::flat_buffer buffer1;
http::read(socket, buffer1, res);
}
std::cout << req << std::endl;
std::cout << res << std::endl;
Спасибо
Когда вы перенаправляете, вы не можете просто «заменить» местоположение в существующем запросе. Вы даже не можете использовать один и тот же сокет, за исключением редких случаев, когда перенаправленная цель находится на той же конечной точке TCP.
Поскольку имя хоста, протокол и путь могли измениться, вам нужно проанализировать местоположение, получить схему, хост, части пути. Затем вы должны снова выполнить правильное разрешение хоста и убедиться, что используете правильное имя хоста в Host
заголовок.
Вот пример, который показывает запрос на повышение лицензии по «неправильному» URL http://boost.org/user/license.html
, который будет быстро перенаправить на http://www.boost.org/user/license.html
,
НОТА Я использовал
network::uri
сделать анализ URI для нас: https://github.com/reBass/uri
#include <iostream>
#include <boost/beast.hpp>
#include <boost/beast/http.hpp>
#include <network/uri.hpp>
#include <boost/asio.hpp>
#include <string>
using boost::asio::ip::tcp;
namespace http = boost::beast::http;
struct Requester {
void do_request(std::string const& url) {
network::uri u{url};
auto const lookup = resolver_.resolve( tcp::resolver::query(u.host().to_string(), u.scheme().to_string()) );
// Set up an HTTP GET request message
tcp::socket socket{ios};
boost::asio::connect(socket, lookup);
http::request<http::string_body> req{http::verb::get, u.path().to_string(), 11};
req.keep_alive(true);
req.set(http::field::host, u.host().to_string());
req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
std::cout << "Target: " << url << "\n";
std::cout << req << "\n";
http::write(socket, req);
boost::beast::flat_buffer buffer;
http::response<http::dynamic_body> res;
http::read(socket, buffer, res);
switch(res.base().result_int()) {
case 301:
std::cout << "Redirecting.....\n";
do_request(res.base()["Location"].to_string());
break;
case 200:
std::cout << res << "\n";
break;
default:
std::cout << "Unexpected HTTP status " << res.result_int() << "\n";
break;
}
}
private:
boost::asio::io_service ios;
tcp::resolver resolver_{ios};
};
int main() {
try {
Requester requester;
requester.do_request("http://boost.org/users/license.html"); // redirects to http://www.boost.org/...
} catch(std::exception const& e) {
std::cerr << "Exception: " << e.what() << "\n";
}
}
Это печатает:
Target: http://boost.org/users/license.html
GET /users/license.html HTTP/1.1
Host: boost.org
User-Agent: Boost.Beast/109Redirecting.....
Target: http://www.boost.org/users/license.html
GET /users/license.html HTTP/1.1
Host: www.boost.org
User-Agent: Boost.Beast/109HTTP/1.1 200 OK
Date: Sun, 27 Aug 2017 22:25:20 GMT
Server: Apache/2.2.15 (CentOS)
Accept-Ranges: bytes
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html
90fd
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>Boost Software License</title>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii" />
<link rel="icon" href="/favicon.ico" type="image/ico" />
<link rel="stylesheet" type="text/css" href="../style-v2/section-boost.css" />
<!--[if IE 7]> <style type="text/css"> body { behavior: url(/style-v2/csshover3.htc); } </style> <![endif]-->
</head><!--
Note: Editing website content is documented at:
http://www.boost.org/development/website_updating.html
-->
<body>
ENTIRE LICENSE BODY SNIPPED
</body>
</html>
0
Других решений пока нет …