handle client ip without forwarding headers
This commit is contained in:
parent
bf4ea51424
commit
6e829eea30
2 changed files with 27 additions and 19 deletions
|
|
@ -21,6 +21,17 @@ pub fn handleWeather(
|
|||
req: *httpz.Request,
|
||||
res: *httpz.Response,
|
||||
) !void {
|
||||
var client_ip_buf: [47]u8 = undefined;
|
||||
// We need IP possibly for location, and possibly to determine implicit Imperial/Metric
|
||||
// Let's get it once here
|
||||
const client_ip = blk: {
|
||||
const client_ip = getClientIpFromHeaders(req);
|
||||
if (client_ip.len == 0) {
|
||||
const full_location = try std.fmt.bufPrint(&client_ip_buf, "{f}", .{req.conn.address});
|
||||
break :blk full_location[0..std.mem.lastIndexOf(u8, full_location, ":").?];
|
||||
}
|
||||
break :blk client_ip;
|
||||
};
|
||||
// Get location from path parameter or query string
|
||||
const location = req.param("location") orelse blk: {
|
||||
// Check query string for location parameter
|
||||
|
|
@ -33,14 +44,14 @@ pub fn handleWeather(
|
|||
|
||||
if (params.location) |loc| {
|
||||
break :blk loc;
|
||||
} else {
|
||||
// Fall back to IP-based detection
|
||||
const client_ip = getClientIP(req);
|
||||
std.log.debug("No location requested, using IP address '{s}'", .{client_ip});
|
||||
break :blk client_ip;
|
||||
}
|
||||
} else break :blk client_ip; // no location, just use client ip instead
|
||||
};
|
||||
|
||||
if (location.len == 0) {
|
||||
res.content_type = .TEXT;
|
||||
res.body = "Sorry, we are unable to determine your location at this time. Try with /<location> or /?location=<location>\n";
|
||||
return;
|
||||
}
|
||||
// Handle special endpoints
|
||||
if (location[0] == ':') {
|
||||
if (std.mem.eql(u8, location, ":help")) {
|
||||
|
|
@ -54,10 +65,10 @@ pub fn handleWeather(
|
|||
}
|
||||
}
|
||||
|
||||
try handleWeatherInternal(opts, req, res, location);
|
||||
try handleWeatherInternal(opts, req, res, location, client_ip);
|
||||
}
|
||||
|
||||
fn getClientIP(req: *httpz.Request) []const u8 {
|
||||
fn getClientIpFromHeaders(req: *httpz.Request) []const u8 {
|
||||
// Check X-Forwarded-For header first (for proxies)
|
||||
if (req.header("x-forwarded-for")) |xff| {
|
||||
return parseXForwardedFor(xff);
|
||||
|
|
@ -68,7 +79,7 @@ fn getClientIP(req: *httpz.Request) []const u8 {
|
|||
return real_ip;
|
||||
}
|
||||
|
||||
// Fall back to empty (no IP available)
|
||||
// Fall back to client connection
|
||||
return "";
|
||||
}
|
||||
|
||||
|
|
@ -86,6 +97,7 @@ fn handleWeatherInternal(
|
|||
req: *httpz.Request,
|
||||
res: *httpz.Response,
|
||||
location_query: []const u8,
|
||||
client_ip: []const u8,
|
||||
) !void {
|
||||
const req_alloc = req.arena;
|
||||
|
||||
|
|
@ -151,12 +163,8 @@ fn handleWeatherInternal(
|
|||
break :blk true;
|
||||
}
|
||||
}
|
||||
const client_ip = getClientIP(req);
|
||||
if (client_ip.len > 0) {
|
||||
if (opts.geoip.isUSIP(client_ip)) {
|
||||
if (client_ip.len > 0 and opts.geoip.isUSIp(client_ip))
|
||||
break :blk true;
|
||||
}
|
||||
}
|
||||
break :blk false;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ fn lookupInternal(mmdb: *c.MMDB_s, ip: []const u8) !c.MMDB_lookup_result_s {
|
|||
return result;
|
||||
}
|
||||
|
||||
pub fn isUSIP(self: *GeoIP, ip: []const u8) bool {
|
||||
pub fn isUSIp(self: *GeoIP, ip: []const u8) bool {
|
||||
const result = lookupInternal(&self.mmdb, ip) catch return false;
|
||||
if (!result.found_entry) return false;
|
||||
|
||||
|
|
@ -156,10 +156,10 @@ test "isUSIP detects US IPs" {
|
|||
defer geoip.deinit();
|
||||
|
||||
// Test that the function doesn't crash with various IPs
|
||||
_ = geoip.isUSIP("8.8.8.8");
|
||||
_ = geoip.isUSIP("1.1.1.1");
|
||||
_ = geoip.isUSIp("8.8.8.8");
|
||||
_ = geoip.isUSIp("1.1.1.1");
|
||||
|
||||
// Test invalid IP returns false
|
||||
const invalid = geoip.isUSIP("invalid");
|
||||
const invalid = geoip.isUSIp("invalid");
|
||||
try std.testing.expect(!invalid);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue