geo information extractor middleware for Hono. Use to extract geo information from request's header or serverless runtime context.
live demo here
- Extracts geo-location information (e.g., country, city, IP).
- Supports multiple serverless environments.
- Lightweight and easy to integrate.
Most serverless runtimes provide valuable information through request headers or platform-specific context APIs. This middleware extracts common geo-location details and other potentially useful data from both request headers and the context object.
-
cloudflare worker: cf properties
-
cloudflare cdn: cf-common-header and visitor-location-header
-
netlify: edge functions specific context object
-
vercel: geo header and more
-
aws cloudfront(lambda@edge): viewer location header
Warning
After testing AWS Lambda@Edge with multiple IP addresses, we found that some geo-related headers(like Country,City,ASN,etc...), as described in the CloudFront documentation, are included for certain IPs, but are missing for others. so, this middleware may not work as expected on lambda@edge
import {getGeo, GeoMiddleware} from "hono-geo-middleware";
const app = new Hono()
app.use('/*', GeoMiddleware())
app.get('/geo', (c) => c.json(getGeo(c)))
export default {
fetch: app.fetch
}
import {getGeo, GeoMiddleware} from "hono-geo-middleware";
const app = new Hono()
const customExtractor = (c:Context) => {
// extract from request
const ip = c.req.header('x-real-ip')
return {
ip
}
}
app.use('/*', GeoMiddleware({
extractors: [customExtractor, 'vercel', 'cloudflare', 'cloudflare-worker'],
}))
app.get('/geo', (c) => c.json(getGeo(c)))
export default {
fetch: app.fetch
}
import { handle } from 'https://esm.sh/hono/netlify'
import {Hono} from "https://esm.sh/hono";
import {GeoMiddleware, getGeo} from "https://esm.sh/hono-geo-middleware";
const app = new Hono()
app.use('/*', GeoMiddleware())
app.get('/geo', (c) => c.json(getGeo(c)))
export default handle(app)
export const config = { path: "/*" }
const example = {
"ip": "1.1.1.1",
"city": "Tokyo",
"country": "Japan",
"countryCode": "JP",
"continent": "AS",
"latitude": "123.5670",
"longitude": "456.7890",
"timezone": "Asia/Tokyo",
"postalCode": "151-0000",
"flag": "🇯🇵",
}
interface Geo {
reqId?: string;
ip?: string;
city?: string;
country?: string;
/* ISO 3166-2 code */
countryCode?: string;
// country region name
region?: string;
/* ISO 3166-2 code */
regionCode?: string;
latitude?: string;
longitude?: string;
continent?: string;
postalCode?: string;
metroCode?: string;
// client
timezone?: string;
asn?: string;
idcRegion?: string;
/** flag emoji */
flag?: string;
}