@@ -11,6 +11,76 @@ use crate::constants::{
1111 HEADER_X_GEO_INFO_AVAILABLE , HEADER_X_GEO_METRO_CODE ,
1212} ;
1313
14+ /// Geographic information extracted from a request.
15+ ///
16+ /// Contains all available geographic data from Fastly's geolocation service,
17+ /// including city, country, continent, coordinates, and DMA/metro code.
18+ #[ derive( Debug , Clone , serde:: Serialize ) ]
19+ pub struct GeoInfo {
20+ /// City name
21+ pub city : String ,
22+ /// Two-letter country code (e.g., "US", "GB")
23+ pub country : String ,
24+ /// Continent name
25+ pub continent : String ,
26+ /// Latitude coordinate
27+ pub latitude : f64 ,
28+ /// Longitude coordinate
29+ pub longitude : f64 ,
30+ /// DMA (Designated Market Area) / metro code
31+ pub metro_code : i64 ,
32+ /// Region code
33+ pub region : Option < String > ,
34+ }
35+
36+ impl GeoInfo {
37+ /// Creates a new `GeoInfo` from a request by performing a geo lookup.
38+ ///
39+ /// This constructor performs a geo lookup based on the client's IP address and returns
40+ /// all available geographic data in a structured format. It does not modify the request
41+ /// or set headers.
42+ ///
43+ /// # Arguments
44+ ///
45+ /// * `req` - The request to extract geographic information from
46+ ///
47+ /// # Returns
48+ ///
49+ /// `Some(GeoInfo)` if geo data is available, `None` otherwise
50+ ///
51+ /// # Example
52+ ///
53+ /// ```ignore
54+ /// if let Some(geo_info) = GeoInfo::from_request(&req) {
55+ /// println!("User is in {} ({})", geo_info.city, geo_info.country);
56+ /// println!("Coordinates: {}", geo_info.coordinates_string());
57+ /// }
58+ /// ```
59+ pub fn from_request ( req : & Request ) -> Option < Self > {
60+ req. get_client_ip_addr ( )
61+ . and_then ( geo_lookup)
62+ . map ( |geo| GeoInfo {
63+ city : geo. city ( ) . to_string ( ) ,
64+ country : geo. country_code ( ) . to_string ( ) ,
65+ continent : format ! ( "{:?}" , geo. continent( ) ) ,
66+ latitude : geo. latitude ( ) ,
67+ longitude : geo. longitude ( ) ,
68+ metro_code : geo. metro_code ( ) ,
69+ region : geo. region ( ) . map ( str:: to_string) ,
70+ } )
71+ }
72+
73+ /// Returns coordinates as a formatted string "latitude,longitude"
74+ pub fn coordinates_string ( & self ) -> String {
75+ format ! ( "{},{}" , self . latitude, self . longitude)
76+ }
77+
78+ /// Checks if a valid metro code is available (non-zero)
79+ pub fn has_metro_code ( & self ) -> bool {
80+ self . metro_code > 0
81+ }
82+ }
83+
1484/// Extracts the DMA (Designated Market Area) code from the request's geolocation data.
1585///
1686/// This function:
0 commit comments