{"analyzedAt":"2022-10-10T20:06:35.385Z","collected":{"metadata":{"name":"geoip-web-api","scope":"unscoped","version":"2.0.2","description":"An AMP-GEO compatible location web API","keywords":["geoip","amp-geo","location","maxmind"],"date":"2022-10-08T18:14:44.811Z","author":{"name":"Matt Mower","email":"mdmower@cmphys.com","username":"mdmower"},"publisher":{"username":"mdmower","email":"mdmower@cmphys.com"},"maintainers":[{"username":"mdmower","email":"mdmower@cmphys.com"}],"repository":{"type":"git","url":"git+https://github.com/mdmower/geoip-web-api.git"},"links":{"npm":"https://www.npmjs.com/package/geoip-web-api","homepage":"https://github.com/mdmower/geoip-web-api#readme","repository":"https://github.com/mdmower/geoip-web-api","bugs":"https://github.com/mdmower/geoip-web-api/issues"},"license":"MIT","dependencies":{"express":"^4.18.1","ip2ldb-reader":"^2.0.3","maxmind":"^4.3.8","minimist":"^1.2.6"},"devDependencies":{"@types/express":"^4.17.14","@types/jest":"^29.1.2","@types/minimist":"^1.2.2","@types/node":"^18.8.3","@typescript-eslint/eslint-plugin":"^5.39.0","@typescript-eslint/parser":"^5.39.0","eslint":"^8.25.0","eslint-config-prettier":"^8.5.0","eslint-plugin-jsdoc":"^39.3.6","eslint-plugin-prettier":"^4.2.1","fs-extra":"^10.1.0","jest":"^29.1.2","prettier":"^2.7.1","rimraf":"^3.0.2","ts-jest":"^29.0.3","typescript":"^4.8.4"},"releases":[{"from":"2022-09-10T00:00:00.000Z","to":"2022-10-10T00:00:00.000Z","count":2},{"from":"2022-07-12T00:00:00.000Z","to":"2022-10-10T00:00:00.000Z","count":2},{"from":"2022-04-13T00:00:00.000Z","to":"2022-10-10T00:00:00.000Z","count":2},{"from":"2021-10-10T00:00:00.000Z","to":"2022-10-10T00:00:00.000Z","count":3},{"from":"2020-10-10T00:00:00.000Z","to":"2022-10-10T00:00:00.000Z","count":6}],"hasTestScript":true,"hasSelectiveFiles":true,"readme":"# geoip-web-api\n\n[![npm](https://img.shields.io/npm/v/geoip-web-api)](https://www.npmjs.com/package/geoip-web-api)\n[![NPM](https://img.shields.io/npm/l/geoip-web-api)](./LICENSE)\n\nA web API for IP-based geolocation. Both IPv4 and IPv6 are supported. Suitable for use as an [amp-geo fallback](https://github.com/ampproject/amphtml/blob/master/spec/amp-framework-hosting.md#amp-geo-fallback-api) when self-hosting the AMP framework.\n\n## GeoIP database and reader\n\n### Option 1: MaxMind\n\nSetup MaxMind's [GeoIP Update](https://dev.maxmind.com/geoip/geoipupdate/) program to fetch and maintain a GeoIP database. Select a [free](https://dev.maxmind.com/geoip/geoip2/geolite2/) or [paid](https://dev.maxmind.com/geoip/geoip2/downloadable/) database in MaxMind DB file format. A sample cron job to let `geoipupdate` check for database updates each day at midnight looks like:\n\n```\n0 0 * * * geoipupdate -f /path/to/GeoIP.conf\n```\n\nThis module uses [node-maxmind](https://github.com/runk/node-maxmind) for the database reader. When the database is updated on the filesystem, the reader should automatically reload without needing to restart this module.\n\n### Option 2: IP2Location\n\nSetup IP2Location's [Download Client](https://www.ip2location.com/free/downloader) script to fetch and maintain a GeoIP database. Select a [free](https://lite.ip2location.com/database) or [paid](https://www.ip2location.com/database) database in BIN file format.\n\nOptionally, if you need subdivision support, also download the [ISO 3166-2 Subdivision Code](https://www.ip2location.com/free/iso3166-2) database in CSV file format.\n\nThis module uses [ip2ldb-reader](https://github.com/mdmower/ip2ldb-reader) for the database reader. When the database is updated on the filesystem, the reader should automatically reload without needing to restart this module.\n\n## Installation\n\nThis module has been tested with Node.js 10, 12, 14, and 16. Feel free to try other versions, but additional support is not promised.\n\nLocal installation\n\n```\nnpm install geoip-web-api\n```\n\nGlobal installation\n\n```\nnpm install -g geoip-web-api\n```\n\n## Options\n\nAll properties are optional, provided the defaults are suitable.\n\n```JavaScript\n{\n  // {number} Log level (0:Off, 1:Error, 2:Warn, 3:Info, 4:Debug)\n  \"logLevel\": 3,\n\n  // {number} Port where HTTP server should listen\n  \"port\": 3000,\n\n  // {Object.<string, boolean>} Enabled output values (see HTTP response section)\n  \"enabledOutputs\": {\n    \"country\": true,\n    \"subdivision\": true,\n    \"ip\": false,\n    \"ip_version\": false,\n    \"data\": false\n  },\n\n  // {boolean} Pretty JSON output\n  \"prettyOutput\": false,\n\n  // {Object.<string, string|null>} Dictionary of HTTP response headers for GET requests\n  \"getHeaders\": {},\n\n  // {Array<string>} Array of GET paths to which HTTP server should respond\n  \"getPaths\": ['/', '/*'],\n\n  // {Object} Allowed cross-origin requests (CORS)\n  \"cors\": {\n    // {Array<string>} Array of allowed CORS origins (exact match)\n    \"origins\": null,\n\n    // {RegEx|string} RegEx test for allowed CORS origins\n    \"originRegEx\": null\n  },\n\n  // {Object.<string, string>} MaxMind database and reader options\n  \"maxmind\": {\n    // {string} Filesystem path to MaxMind database (in MMDB format)\n    \"dbPath\": \"./GeoLite2-Country.mmdb\"\n  },\n\n  // {Object.<string, string>} IP2Location database and reader options\n  \"ip2location\": {\n    // {string} Filesystem path to IP2Location database (in BIN format)\n    \"dbPath\": \"\",\n\n    // {string} Filesystem path to IP2Location ISO 3166-2 Subdivision Code database (in CSV format)\n    \"subdivisionCsvPath\": \"\"\n  }\n}\n```\n\n**Additional information**\n\n- `enabledOutputs` - If an output is enabled but is not supported by the database, it will not be output in the final response.\n\n- `getHeaders` - Headers can be removed from the response by setting their values to `null`. The `Content-Type` and `Content-Length` headers are generated automatically and cannot be removed; it is possible to change the `Content-Type` header to another valid MIME type, but it is not possible to alter `Content-Length`. The `ETag` header additionally supports special values `\"strong\"` and `\"weak\"` to specify strong or weak ETag generation, respectively (weak by default).\n\n- `getPaths` - See Express [Route paths](https://expressjs.com/en/guide/routing.html#route-paths) documentation for allowed route patterns. Notice that the default configuration matches requests to any path.\n\n- `cors.origins` and `cors.originRegEx` - If the incoming request has an `Origin` HTTP header that satisfies one of these tests (is in `cors.origins` array or satisfies `cors.originRegEx` RegEx test), then an `Access-Control-Allow-Origin` header will be appended to the response with value equal to the `Origin` header. Note that if `cors.originRegEx` is available as a string, the `RegExp` object will be built with `new RegExp(cors.originRegEx, 'i')`.\n\n- `maxmind` and `ip2location` - Only one of these properties should be provided. If both have valid `dbPath` properties, then MaxMind takes precedence.\n\nWhen running this module as a command line application, these options should be saved in a JSON configuration file whose path is passed to the application with argument `--config`. When using this module in your own Node.js application, these options should be passed to the `GeoIpWebApi` constructor. See Usage section below.\n\n### Example options\n\n```JSON\n{\n  \"logLevel\": 1,\n  \"port\": 8080,\n  \"enabledOutputs\": {\n    \"ip\": true,\n    \"data\": true\n  },\n  \"getHeaders\": {\n    \"cache-control\": \"private, max-age=3600\",\n    \"X-Content-Type-Options\": \"nosniff\"\n  },\n  \"getPaths\": [\"/geoip/?\"],\n  \"cors\": {\n    \"origins\": [\"http://example.com\", \"http://example.net\"],\n    \"originRegEx\": \"^https://[a-z0-9\\\\-]+\\\\.example\\\\.(com|net)$\"\n  },\n  \"maxmind\": {\n    \"dbPath\": \"/path/to/GeoLite2-City.mmdb\"\n  }\n}\n```\n\n## Usage\n\n### Command line interface\n\nIf installed globally:\n\n```bash\ngeoip-web-api --config=\"/path/to/config.json\"\n```\n\nIf installed locally:\n\n```bash\nnpx geoip-web-api --config=\"/path/to/config.json\"\n```\n\n### Node.js module\n\n```JavaScript\nimport GeoIpWebApi from 'geoip-web-api';\n// Or using require() syntax:\n// const GeoIpWebApi = require('geoip-web-api').GeoIpWebApi;\nconst options = {...};\nconst geoIpWebApi = new GeoIpWebApi(options);\n\n// Start HTTP server\nawait geoIpWebApi.start();\n\n// Stop HTTP server\nawait geoIpWebApi.stop();\n\n// Check whether HTTP server is running\nlet isRunning = geoIpWebApi.isRunning();\n```\n\n## HTTP response\n\nThe response body is `application/json` and contains the following data:\n\n```JavaScript\n{\n  \"country\": {string},      // ISO 3166-1 alpha-2 country code\n  \"subdivision\": {string},  // Subdivision part of ISO 3166-2 country-subdivision code\n  \"ip\": {string},           // Request IP\n  \"ip_version\": {number}    // Request IP version (4 or 6, or 0 if IP is not valid)\n  \"data\": {object}          // Complete database result\n}\n```\n\nThe schema for `data` depends on the database used.\n\nResponse conforms to [AMP-GEO fallback API schema 0.2](https://github.com/ampproject/amphtml/blob/f744c490be41f2553b24cb9f0f0efb5136477e79/extensions/amp-geo/0.1/amp-geo.js#L286-L307)\n\n```JSON\n{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"type\": \"object\",\n  \"properties\": {\n    \"country\": {\n      \"type\": \"string\",\n      \"title\": \"ISO 3166-1 alpha-2 (case insensitive) country code of client request\",\n      \"default\": \"\",\n      \"pattern\": \"^[a-zA-Z]{2}$\"\n    },\n    \"subdivision\": {\n      \"type\": \"string\",\n      \"title\": \"Subdivision part of ISO 3166-2 (case insensitive) country-subdivision code of client request\",\n      \"default\": \"\",\n      \"pattern\": \"^[a-zA-Z0-9]{1,3}$\"\n    }\n  },\n  \"required\": [\n    \"country\"\n  ]\n}\n```\n\n### Sample response\n\n```JSON\n{\n  \"country\": \"US\",\n  \"subdivision\": \"CA\"\n}\n```\n\n## Reverse proxy\n\nThe HTTP server ([Express](https://expressjs.com/)) in this module is designed to run behind a reverse proxy. It has been configured to trust the leftmost IP in the `X-Forwarded-For` request header (see [documentation](https://expressjs.com/en/guide/behind-proxies.html) for `trust proxy = true`).\n\n### Sample Nginx location block\n\nListen for requests to `/geoip/` and forward to localhost port `8080`:\n\n```Nginx\nlocation ~ ^/geoip/ {\n    proxy_set_header X-Forwarded-For $remote_addr;\n    proxy_pass http://127.0.0.1:8080;\n    proxy_redirect off;\n}\n```\n\n## License\n\nMIT"},"npm":{"downloads":[{"from":"2022-10-09T00:00:00.000Z","to":"2022-10-10T00:00:00.000Z","count":17},{"from":"2022-10-03T00:00:00.000Z","to":"2022-10-10T00:00:00.000Z","count":54},{"from":"2022-09-10T00:00:00.000Z","to":"2022-10-10T00:00:00.000Z","count":72},{"from":"2022-07-12T00:00:00.000Z","to":"2022-10-10T00:00:00.000Z","count":131},{"from":"2022-04-13T00:00:00.000Z","to":"2022-10-10T00:00:00.000Z","count":261},{"from":"2021-10-10T00:00:00.000Z","to":"2022-10-10T00:00:00.000Z","count":451}],"starsCount":0},"github":{"starsCount":0,"forksCount":0,"subscribersCount":2,"issues":{"count":1,"openCount":0,"distribution":{"3600":0,"10800":0,"32400":0,"97200":0,"291600":0,"874800":0,"2624400":0,"7873200":0,"23619600":1,"70858800":0,"212576400":0},"isDisabled":false},"commits":[{"from":"2022-10-03T00:00:00.000Z","to":"2022-10-10T00:00:00.000Z","count":0},{"from":"2022-09-10T00:00:00.000Z","to":"2022-10-10T00:00:00.000Z","count":1},{"from":"2022-07-12T00:00:00.000Z","to":"2022-10-10T00:00:00.000Z","count":1},{"from":"2022-04-13T00:00:00.000Z","to":"2022-10-10T00:00:00.000Z","count":1},{"from":"2021-10-10T00:00:00.000Z","to":"2022-10-10T00:00:00.000Z","count":2}]},"source":{"files":{"readmeSize":8383,"testsSize":13137},"linters":["editorconfig","eslint","prettier"]}},"evaluation":{"quality":{"carefulness":0.9199999999999999,"tests":0.6,"health":1,"branding":0},"popularity":{"communityInterest":2,"downloadsCount":43.666666666666664,"downloadsAcceleration":0.3446917808219178,"dependentsCount":0},"maintenance":{"releasesFrequency":1,"commitsFrequency":0.9,"openIssues":1,"issuesDistribution":0.9}},"score":{"final":0.6110412449894731,"detail":{"quality":0.8364556389013833,"popularity":0.028989318382497787,"maintenance":0.9998808339576686}}}