@@ -48,32 +48,10 @@ std::string get_error_time_format() {
4848 return ss.str ();
4949}
5050
51- std::string get_client_ip (const Request &req) {
52- // Check for X-Forwarded-For header first (common in reverse proxy setups)
53- auto forwarded_for = req.get_header_value (" X-Forwarded-For" );
54- if (!forwarded_for.empty ()) {
55- // Get the first IP if there are multiple
56- auto comma_pos = forwarded_for.find (' ,' );
57- if (comma_pos != std::string::npos) {
58- return forwarded_for.substr (0 , comma_pos);
59- }
60- return forwarded_for;
61- }
62-
63- // Check for X-Real-IP header
64- auto real_ip = req.get_header_value (" X-Real-IP" );
65- if (!real_ip.empty ()) { return real_ip; }
66-
67- // Fallback to remote address (though cpp-httplib doesn't provide this
68- // directly) For demonstration, we'll use a placeholder
69- return " 127.0.0.1" ;
70- }
71-
7251// NGINX Combined log format:
7352// $remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent
7453// "$http_referer" "$http_user_agent"
7554void nginx_access_logger (const Request &req, const Response &res) {
76- auto remote_addr = get_client_ip (req);
7755 std::string remote_user =
7856 " -" ; // cpp-httplib doesn't have built-in auth user tracking
7957 auto time_local = get_time_format ();
@@ -86,7 +64,7 @@ void nginx_access_logger(const Request &req, const Response &res) {
8664 if (http_user_agent.empty ()) http_user_agent = " -" ;
8765
8866 std::cout << std::format (" {} - {} [{}] \" {}\" {} {} \" {}\" \" {}\" " ,
89- remote_addr, remote_user, time_local, request,
67+ req. remote_addr , remote_user, time_local, request,
9068 status, body_bytes_sent, http_referer,
9169 http_user_agent)
9270 << std::endl;
@@ -100,16 +78,15 @@ void nginx_error_logger(const Error &err, const Request *req) {
10078 std::string level = " error" ;
10179
10280 if (req) {
103- auto client_ip = get_client_ip (*req);
10481 auto request =
10582 std::format (" {} {} {}" , req->method , req->path , req->version );
10683 auto host = req->get_header_value (" Host" );
10784 if (host.empty ()) host = " -" ;
10885
10986 std::cerr << std::format (" {} [{}] {}, client: {}, request: "
11087 " \" {}\" , host: \" {}\" " ,
111- time_local, level, to_string (err), client_ip,
112- request, host)
88+ time_local, level, to_string (err),
89+ req-> remote_addr , request, host)
11390 << std::endl;
11491 } else {
11592 // If no request context, just log the error
@@ -131,6 +108,10 @@ void print_usage(const char *program_name) {
131108 std::cout << " Format: mount_point:document_root"
132109 << std::endl;
133110 std::cout << " (default: /:./html)" << std::endl;
111+ std::cout << " --trusted-proxy <ip> Add trusted proxy IP address"
112+ << std::endl;
113+ std::cout << " (can be specified multiple times)"
114+ << std::endl;
134115 std::cout << " --version Show version information"
135116 << std::endl;
136117 std::cout << " --help Show this help message" << std::endl;
@@ -140,13 +121,17 @@ void print_usage(const char *program_name) {
140121 << " --host localhost --port 8080 --mount /:./html" << std::endl;
141122 std::cout << " " << program_name
142123 << " --host 0.0.0.0 --port 3000 --mount /api:./api" << std::endl;
124+ std::cout << " " << program_name
125+ << " --trusted-proxy 192.168.1.100 --trusted-proxy 10.0.0.1"
126+ << std::endl;
143127}
144128
145129struct ServerConfig {
146130 std::string hostname = " localhost" ;
147131 int port = 8080 ;
148132 std::string mount_point = " /" ;
149133 std::string document_root = " ./html" ;
134+ std::vector<std::string> trusted_proxies;
150135};
151136
152137enum class ParseResult { SUCCESS, HELP_REQUESTED, VERSION_REQUESTED, ERROR };
@@ -205,6 +190,14 @@ ParseResult parse_command_line(int argc, char *argv[], ServerConfig &config) {
205190 } else if (strcmp (argv[i], " --version" ) == 0 ) {
206191 std::cout << CPPHTTPLIB_VERSION << std::endl;
207192 return ParseResult::VERSION_REQUESTED;
193+ } else if (strcmp (argv[i], " --trusted-proxy" ) == 0 ) {
194+ if (i + 1 >= argc) {
195+ std::cerr << " Error: --trusted-proxy requires an IP address argument"
196+ << std::endl;
197+ print_usage (argv[0 ]);
198+ return ParseResult::ERROR;
199+ }
200+ config.trusted_proxies .push_back (argv[++i]);
208201 } else {
209202 std::cerr << " Error: Unknown option '" << argv[i] << " '" << std::endl;
210203 print_usage (argv[0 ]);
@@ -218,6 +211,11 @@ bool setup_server(Server &svr, const ServerConfig &config) {
218211 svr.set_logger (nginx_access_logger);
219212 svr.set_error_logger (nginx_error_logger);
220213
214+ // Set trusted proxies if specified
215+ if (!config.trusted_proxies .empty ()) {
216+ svr.set_trusted_proxies (config.trusted_proxies );
217+ }
218+
221219 auto ret = svr.set_mount_point (config.mount_point , config.document_root );
222220 if (!ret) {
223221 std::cerr
@@ -285,6 +283,16 @@ int main(int argc, char *argv[]) {
285283 << std::endl;
286284 std::cout << " Mount point: " << config.mount_point << " -> "
287285 << config.document_root << std::endl;
286+
287+ if (!config.trusted_proxies .empty ()) {
288+ std::cout << " Trusted proxies: " ;
289+ for (size_t i = 0 ; i < config.trusted_proxies .size (); ++i) {
290+ if (i > 0 ) std::cout << " , " ;
291+ std::cout << config.trusted_proxies [i];
292+ }
293+ std::cout << std::endl;
294+ }
295+
288296 std::cout << " Press Ctrl+C to shutdown gracefully..." << std::endl;
289297
290298 auto ret = svr.listen (config.hostname , config.port );
0 commit comments