Below is my sample restful web service created using C++ and Boost Beast.
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/version.hpp>
#include <boost/asio.hpp>
#include <chrono>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <memory>
#include <string>
namespace beast = boost::beast;
namespace http = beast::http;
namespace net = boost::asio;
using tcp = boost::asio::ip::tcp;
namespace my_program_state
{
std::size_t
request_count()
{
static std::size_t count = 0;
return ++count;
}
std::time_t
now()
{
return std::time(0);
}
}
class http_connection : public std::enable_shared_from_this<http_connection>
{
public:
http_connection(tcp::socket socket)
: socket_(std::move(socket))
{
}
void start()
{
read_request();
check_deadline();
}
private:
tcp::socket socket_;
beast::flat_buffer buffer_{8192};
http::request<http::dynamic_body> request_;
http::response<http::dynamic_body> response_;
net::steady_timer deadline_{ socket_.get_executor(), std::chrono::seconds(60) };
void read_request()
{
auto self = shared_from_this();
http::async_read(
socket_,
buffer_,
request_,
[self](beast::error_code ec, std::size_t bytes_transferred)
{
boost::ignore_unused(bytes_transferred);
if(!ec)
self->process_request();
}
);
}
void process_request()
{
response_.version(request_.version());
response_.keep_alive(false);
switch(request_.method())
{
case http::verb::get:
response_.result(http::status::ok);
response_.set(http::field::server, "Beast");
create_response();
break;
default:
response_.result(http::status::bad_request);
response_.set(http::field::content_type, "text/plain");
beast::ostream(response_.body())
<< "Invalid request-method '"
<< std::string(request_.method_string())
<< "'";
break;
}
write_response();
}
void create_response()
{
if(request_.target() == "/json")
{
response_.set(http::field::content_type, "application/json");
response_.set(http::field::access_control_allow_origin, "*");
response_.set(http::field::access_control_allow_headers, "*");
response_.set(http::field::access_control_allow_methods, "GET, POST, PATCH, PUT, DELETE, OPTIONS");
beast::ostream(response_.body())
<< "{\"a\":{\"b\":\"c\"}}";
}
else
{
response_.result(http::status::not_found);
response_.set(http::field::content_type, "text/plain");
beast::ostream(response_.body()) << "File not found\r\n";
}
}
void write_response()
{
auto self = shared_from_this();
response_.content_length(response_.body().size());
http::async_write(
socket_,
response_,
[self](beast::error_code ec, std::size_t)
{
self->socket_.shutdown(tcp::socket::shutdown_send, ec);
self->deadline_.cancel();
}
);
}
void check_deadline()
{
auto self = shared_from_this();
deadline_.async_wait(
[self](beast::error_code ec)
{
if(!ec)
{
self->socket_.close(ec);
}
}
);
}
};
void http_server(tcp::acceptor& acceptor, tcp::socket& socket)
{
acceptor.async_accept(socket, [&](beast::error_code ec) {
if(!ec) std::make_shared<http_connection>(std::move(socket))->start();
http_server(acceptor, socket);
});
}
int main(int argc, char* argv[])
{
try
{
if(argc != 3)
{
std::cerr << "Usage: " << argv[0] << " <address> <port>\n";
std::cerr << " For IPv4, try:\n";
std::cerr << " receiver 0.0.0.0 80\n";
std::cerr << " For IPv6, try:\n";
std::cerr << " receiver 0::0 80\n";
return EXIT_FAILURE;
}
auto const address = net::ip::make_address(argv[1]);
unsigned short port = static_cast<unsigned short>(std::atoi(argv[2]));
net::io_context ioc{1};
tcp::acceptor acceptor{ioc, {address, port}};
tcp::socket socket{ioc};
http_server(acceptor, socket);
ioc.run();
}
catch(std::exception const& e)
{
std::cerr << "Error: " << e.what() << std::endl;
return EXIT_FAILURE;
}
}
I run this web server as following.
./main 192.168.10.100 8081
Below is my JavaScript client making a GET request from another IP address e.g. 192.168.10.101.
window.axios.get("http://192.168.10.100:8081/json")
.then(res => {
console.log(res.data);
})
.catch(err => {
console.log(err.response);
});
Due to Referrer Policystrict-origin-when-cross-origin
, I cannot get JSON data responded by the web service. I have already added response headers but it still does not help. How can I solve this issue?