45 lines
1.4 KiB
C++
45 lines
1.4 KiB
C++
|
#include <http/proxy_address.hpp>
|
||
|
#include <base/assert.hpp>
|
||
|
#include <base/types.hpp>
|
||
|
|
||
|
namespace base::http {
|
||
|
|
||
|
asio::ip::address GetProxyAddress(asio::ip::address fallback, beast::http::request<beast::http::string_body>& req) {
|
||
|
#ifdef BASE_HTTP_REVERSE_PROXY_SUPPORT
|
||
|
auto forwarded_for = req[
|
||
|
#ifndef BASE_HTTP_CLOUDFLARE
|
||
|
"X-Forwarded-For"
|
||
|
#else
|
||
|
"CF-Connecting-IP"
|
||
|
#endif
|
||
|
];
|
||
|
|
||
|
if(forwarded_for == "") {
|
||
|
// if no header was provided, just return that hop
|
||
|
return fallback;
|
||
|
} else {
|
||
|
bsys::error_code ec;
|
||
|
asio::ip::address ip;
|
||
|
|
||
|
// X-Forwarded-For is a tokenized list, where the first element is always the client hop.
|
||
|
// We only need to worry about the client hop.
|
||
|
|
||
|
if(forwarded_for.find(',') != beast::string_view::npos) {
|
||
|
ip = asio::ip::make_address(std::string_view(forwarded_for.data(), forwarded_for.find(',')), ec);
|
||
|
} else {
|
||
|
ip = asio::ip::make_address(std::string_view(forwarded_for.data(), forwarded_for.length()), ec);
|
||
|
}
|
||
|
|
||
|
// The X-Forwarded-For header is not controlled by user input (and should *not* be, with a properly written proxy server),
|
||
|
// so if this CHECK fires, you're probably in a bad enough situation not worth continuing anyways.
|
||
|
BASE_CHECK(!ec, "Invalid IP address in proxy IP header. Header: \"{}\"",
|
||
|
std::string_view(forwarded_for.data(), forwarded_for.length()));
|
||
|
return ip;
|
||
|
}
|
||
|
#else
|
||
|
return fallback;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
} // namespace base::http
|