Hono Geo Middleware

raw JSON →
0.1.2 verified Thu Apr 23 auth: no javascript

The `hono-geo-middleware` package provides a specialized Hono middleware for extracting geographical location data from incoming HTTP requests. It is designed to work across various serverless environments, including Cloudflare Workers, Vercel, Netlify Edge Functions, and AWS CloudFront/Lambda@Edge, by intelligently parsing platform-specific headers and context objects. The middleware normalizes this data into a consistent `Geo` interface, offering details like IP address, city, country, country code, and timezone. Currently at version 0.1.2, the package is in its early stages of development, suggesting a potentially frequent release cadence for enhancements and bug fixes. Its primary differentiator is simplifying geo-IP data access within Hono applications, abstracting the complexities of diverse serverless runtime environments and supporting custom extraction logic.

error Cannot find module 'hono-geo-middleware'
cause The package has not been installed or there is a mismatch in module resolution for ESM.
fix
Install the package using your package manager: npm install hono-geo-middleware or yarn add hono-geo-middleware. For Deno, use the esm.sh import URL: import { GeoMiddleware } from 'https://esm.sh/hono-geo-middleware';
error TypeError: Cannot read properties of undefined (reading 'ip')
cause The `getGeo(c)` function returned `undefined`, likely because the `GeoMiddleware` was not applied to the current route, or no geo data could be extracted by any configured extractor.
fix
Ensure app.use('/*', GeoMiddleware()) or a more specific path is correctly applied before the route attempting to read geo data. Also, handle cases where geo data might not be available, e.g., const ip = getGeo(c)?.ip;
error Cannot find name 'Context'
cause When defining a `customExtractor` in TypeScript, the `Context` type from Hono needs to be explicitly imported.
fix
Add import { Context } from 'hono'; to the top of your TypeScript file where the custom extractor is defined.
breaking As of version 0.1.2, the package is in early development. Minor version updates may introduce breaking changes to the `Geo` interface, middleware options, or extraction logic without strict adherence to semantic versioning for non-major releases.
fix Always review the changelog when updating minor versions and pin exact versions in production environments to prevent unexpected breakage.
gotcha The availability and accuracy of geolocation data are highly dependent on the hosting serverless environment, client's network configuration, and specific headers provided. Not all fields in the `Geo` interface may be populated for every request.
fix Implement robust error handling and fallback logic when consuming geo data, checking for `undefined` or null values for specific properties. For example: `c.json(getGeo(c)?.countryCode ?? 'unknown')`.
gotcha Processing and storing geolocation data carries significant privacy implications (e.g., GDPR, CCPA). The middleware extracts the data but does not provide any compliance mechanisms.
fix Developers are solely responsible for ensuring their use of geolocation data complies with all applicable privacy laws and regulations, including obtaining user consent where required.
gotcha When using multiple extractors, especially custom ones, the order of `extractors` in the `GeoMiddleware` configuration matters. Later extractors may overwrite data provided by earlier ones if they target the same fields.
fix Carefully consider the order of extractors, placing general or less specific ones before more precise or custom ones if overriding is desired, or vice-versa if specific extractors should take precedence.
npm install hono-geo-middleware
yarn add hono-geo-middleware
pnpm add hono-geo-middleware

Initializes a Hono application, applies the GeoMiddleware to all routes, and provides an endpoint to retrieve the extracted geolocation data.

import { Hono } from 'hono';
import { GeoMiddleware, getGeo } from 'hono-geo-middleware';

const app = new Hono();

// Apply the GeoMiddleware to all routes
app.use('/*', GeoMiddleware());

// Define a route to expose the extracted geo information
app.get('/geo', (c) => {
  const geoData = getGeo(c);
  if (geoData) {
    return c.json(geoData);
  } else {
    return c.json({ message: 'Geolocation data not available' }, 404);
  }
});

// Example of a root route
app.get('/', (c) => c.text('Hello Hono! Geo data available at /geo'));

export default {
  fetch: app.fetch
};