I need to detect if the request was sent through ajax or not using the boost beast http parser
Some frameworks for http in other programming languages provide this capability. But how can this be done with boost::beast?
I know that it depends on the data that the client sends and this data cannot always be trusted. But what is the correct way to determine an Ajax request based on client data, if the client sent all the data necessary for this through the browser?
This really has nothing to do with Beast, but taking the ideas from this page: https://www.geeksforgeeks.org/how-to-detect-ajax-request-to-normal-request-in-node-js/
- Check the headers of the request and if it contains
HTTP_X_REQUESTED_WITH
having a value of XMLHttpRequest then it is an ajax request.- When you make an AJAX request, it adds content type
application/json
to the header of the request. So if the request contains the header then it is the AJAX- If the
referer
header is different from thehost
header then it is an AJAX request- If the
sec-fetch-dest
header is equal toempty
then it is an AJAX request
Disclaimer: I don't think these approaches are reliable let alone secure, but the demo below should give you some tools to translate your own requirements into beast code.
#include <boost/beast.hpp>
#include <iostream>
namespace beast = boost::beast;
namespace http = beast::http;
namespace net = boost::asio;
using net::ip::tcp;
using Request = http::request<http::string_body>;
boost::optional<beast::string_view> header(Request const& req, beast::string_view name) {
auto it = req.find(name);
if (it != req.end())
return it->value();
return {};
}
int main() {
net::io_context ioc;
tcp::acceptor acc(ioc, {{}, 8989});
while (true) {
Request req;
auto sock = acc.accept();
beast::flat_buffer buf;
read(sock, buf, req);
bool is_ajax = req.count("HTTP_X_REQUESTED_WITH") // 1.
|| header(req, "referer") != header(req, "host") // 3.
|| header(req, "sec-fetch-dest") == beast::string_view("empty"); // 4.
std::cout << (is_ajax ? "AJAX " : "Regular ") //
<< req.method_string() << " request " //
<< " for " << req.target() //
<< std::endl;
}
}
For some tests:
g++ -std=c++20 -O2 -Wall -pedantic -pthread main.cpp
./a.out&
sleep 1; curl -s http://127.0.0.1:8989/demo1 -d @main.cpp
sleep 1; curl -sH 'referer: 127.0.0.1:8989' "http://127.0.0.1:8989/demo2?the=works"
Prints
AJAX POST request for /demo1
Regular GET request for /demo2?the=works