# 🌍 Bitip - GeoIP Lookup Service Bitip is a professional GeoIP lookup service that provides IP geolocation data through a REST API and user-friendly web interface. Built with Express.js, TypeScript, React, and MaxMind GeoLite2 databases. ## ✨ Features - **πŸ” IP Geolocation Lookup**: Get detailed location information for any public IP address - **🌐 Web Interface**: Clean, professional web UI with interactive maps - **πŸ“‘ REST API**: Comprehensive API for single and batch IP lookups - **πŸ“¦ .NET Client Library**: Official Bitip.Client NuGet package with strongly-typed models and async support - **πŸ“¦ Node.js Client Library**: Official @flare/bitip-client npm package with TypeScript support and modern API - **πŸ—ΊοΈ Interactive Maps**: Static preview and interactive map popups using OpenStreetMap/Leaflet - **πŸ” API Key Authentication**: Secure access with configurable rate limiting - **⚑ Performance**: In-memory caching and efficient database access - **πŸ“Š Structured Logging**: Optional integration with Seq for advanced logging - **🐳 Docker Ready**: Production deployment with Docker and geoipupdate integration - **πŸ”§ Configurable**: Runtime configuration via environment variables ## πŸ“š Client Libraries ### .NET / C# Official NuGet package with full async/await support and dependency injection integration: ```bash dotnet add package Bitip.Client ``` ```csharp // Register in your DI container services.UseBitipClient("https://your-bitip-instance.com/api", "your-api-key"); // Inject and use public class MyService { private readonly IBitipClient _bitipClient; public MyService(IBitipClient bitipClient) { _bitipClient = bitipClient; } public async Task LookupAsync(string ip) { return await _bitipClient.GetIpLocation(ip); } } ``` See [src/clients/dotnet/Bitip.Client/README.md](src/clients/dotnet/Bitip.Client/README.md) for complete documentation. ### Node.js / TypeScript Official npm package with full TypeScript support and modern async/await API: ```bash npm install @flare/bitip-client ``` ```typescript import { BitipClient } from '@flare/bitip-client'; // Create client instance const client = new BitipClient({ baseUrl: 'https://your-bitip-instance.com', apiKey: 'your-api-key', }); // Perform IP lookup const location = await client.getIpLocation('8.8.8.8'); console.log(location.country); // United States ``` See [src/clients/node/README.md](src/clients/node/README.md) for complete documentation. ### Other Languages Use the REST API directly - see API documentation below. ## πŸš€ Quick Start ### Local Development (No Docker Required) #### Prerequisites - Node.js >= 18.0.0 - npm >= 9.0.0 - MaxMind GeoLite2 databases (download from https://www.maxmind.com/en/geolite2/signup or use geoipupdate) #### 1. Clone and Setup ```bash git clone cd Bitip ``` #### 2. Install Dependencies ```bash npm run install:all ``` #### 3. Configure Environment Create a `.env` file in the root directory: ```env # API Keys (change these for production!) FRONTEND_API_KEY=frontend-dev-key EXTERNAL_API_KEYS=external-dev-key-1,external-dev-key-2 # Server Configuration PORT=5172 BASE_PATH=/ NODE_ENV=development ENABLE_HTTPS_SECURITY=false LOG_LEVEL=debug # debug | info | warning | error # Database Path - Point to your MaxMind databases location # Both GeoLite2-City.mmdb and GeoLite2-ASN.mmdb are required MAXMIND_DB_PATH=D:\tools\maxmind-dbs # Windows # MAXMIND_DB_PATH=/usr/share/maxmind # Linux/Mac # Rate Limiting Configuration FRONTEND_RATE_WINDOW_MS=60000 FRONTEND_RATE_MAX=30 EXTERNAL_RATE_WINDOW_MS=60000 EXTERNAL_RATE_MAX=1000 # Batch Configuration BATCH_LIMIT=100 DEBOUNCE_MS=2000 # Seq Logging (Optional) # SEQ_URL=http://localhost:5341 # SEQ_API_KEY=your-seq-api-key ``` #### 4. Start Development Servers ```bash npm run dev ``` This will start: - Backend API server on http://localhost:5172 - Frontend dev server on http://localhost:5173 (or next available port) - Frontend proxies API requests to backend #### 5. Access the Application - **Web Interface**: http://localhost:5173 (or the port shown in console) - **API Endpoint**: http://localhost:5172/api - **Health Check**: http://localhost:5172/api/health ### Production Deployment (Docker) #### Prerequisites - Docker and Docker Compose - MaxMind GeoLite2 account (free): https://www.maxmind.com/en/geolite2/signup #### 1. Configure Environment Edit `.env` file with your MaxMind credentials and logging level: ```env GEOIPUPDATE_ACCOUNT_ID=your_account_id_here GEOIPUPDATE_LICENSE_KEY=your_license_key_here FRONTEND_API_KEY=your-secure-frontend-api-key-here EXTERNAL_API_KEYS=your-secure-external-api-key-1,your-secure-external-api-key-2 LOG_LEVEL=warning # Recommended for production (debug | info | warning | error) ``` #### 2. Start Services ```bash docker-compose up -d ``` **Or with Docker run:** ```bash # Build image docker build -t bitip-geoip:latest . # Run with custom log level docker run -d \ -p 5172:5172 \ -e LOG_LEVEL=warning \ -e FRONTEND_API_KEY=your-api-key \ -v /path/to/maxmind-dbs:/usr/share/maxmind \ bitip-geoip:latest ``` **Available log levels:** - `debug` - All logs (verbose, for development/troubleshooting) - `info` - Info + warnings + errors (default) - `warning` - Warnings + errors only (recommended for production) - `error` - Errors only (minimal logging) #### 3. Access the Service - **Web Interface**: http://localhost:5172 - **API Endpoint**: http://localhost:5172/api - **Health Check**: http://localhost:5172/api/health ## πŸ“– API Documentation ### Authentication All API requests require an API key sent via header or query parameter: ```bash # Via Header (recommended) curl -H "X-API-Key: your-api-key" http://localhost:5172/api/lookup?ip=8.8.8.8 # Via Query Parameter curl "http://localhost:5172/api/lookup?ip=8.8.8.8&apikey=your-api-key" ``` ### Endpoints #### Get Current IP ```http GET /api/ip ``` Returns the client's current IP address. **Response:** ```json { "ip": "203.0.113.42" } ``` #### Simple IP Lookup ```http GET /api/lookup?ip=8.8.8.8 ``` Returns basic location information: ```json { "ip": "8.8.8.8", "country": "United States", "country_code": "US", "is_in_european_union": false, "region": "California", "region_code": "CA", "city": "Mountain View", "latitude": 37.4056, "longitude": -122.0775, "timezone": "America/Los_Angeles", "postal_code": "94043", "continent_code": "NA", "continent_name": "North America", "organization": "Google LLC", "asn": 15169 } ``` #### Detailed IP Lookup ```http GET /api/lookup/detailed?ip=8.8.8.8 ``` Returns comprehensive MaxMind database information including all available fields. #### Batch IP Lookup ```http POST /api/lookup/batch Content-Type: application/json { "ips": ["8.8.8.8", "1.1.1.1", "208.67.222.222"] } ``` **Response:** ```json { "results": [ { "ip": "8.8.8.8", "country": "United States", ... }, { "ip": "1.1.1.1", "country": "Australia", ... } ] } ``` #### Health Check ```http GET /api/health ``` Returns service health status including database connectivity. ### Error Handling The API returns appropriate HTTP status codes: - `400` - Bad Request (invalid IP, private IP, validation errors) - `401` - Unauthorized (missing or invalid API key) - `404` - Not Found (IP not in database) - `429` - Too Many Requests (rate limit exceeded) - `500` - Internal Server Error - `503` - Service Unavailable (database maintenance) ## πŸ› οΈ Development ### Project Structure ``` Bitip/ β”œβ”€β”€ src/ β”‚ β”œβ”€β”€ backend/ # Express.js API server β”‚ β”‚ β”œβ”€β”€ handlers/ # Route handlers (separated by concern) β”‚ β”‚ β”œβ”€β”€ middleware/ # Express middleware (auth, rate limiting, validators, errorHandler) β”‚ β”‚ β”œβ”€β”€ routes/ # API routes (declarative, minimal) β”‚ β”‚ β”œβ”€β”€ services/ # Business logic (GeoIP, config, logger) β”‚ β”‚ β”œβ”€β”€ tests/ # Test suite (integration + unit tests) β”‚ β”‚ β”‚ β”œβ”€β”€ integration/ # API endpoint tests (25 tests) β”‚ β”‚ β”‚ β”œβ”€β”€ unit/ # Middleware unit tests (18 tests) β”‚ β”‚ β”‚ └── setup.ts # Test configuration and helpers β”‚ β”‚ β”œβ”€β”€ types/ # TypeScript type definitions β”‚ β”‚ β”œβ”€β”€ utils/ # Utilities (errors, paths) β”‚ β”‚ β”œβ”€β”€ app.ts # Express app factory (without server) β”‚ β”‚ β”œβ”€β”€ server.ts # Server startup and lifecycle β”‚ β”‚ β”œβ”€β”€ index.ts # Entry point (backward compatible) β”‚ β”‚ β”œβ”€β”€ vitest.config.ts # Test configuration β”‚ β”‚ β”œβ”€β”€ nodemon.json # Nodemon configuration β”‚ β”‚ β”œβ”€β”€ tsconfig.json # TypeScript configuration β”‚ β”‚ └── package.json # Backend dependencies β”‚ └── frontend/ # React web application β”‚ β”œβ”€β”€ src/ β”‚ β”‚ β”œβ”€β”€ components/ # React components (MapComponent) β”‚ β”‚ β”œβ”€β”€ services/ # API client services β”‚ β”‚ β”œβ”€β”€ types/ # TypeScript types β”‚ β”‚ β”œβ”€β”€ App.tsx # Main App component β”‚ β”‚ β”œβ”€β”€ App.css # Application styles β”‚ β”‚ └── main.tsx # React entry point β”‚ β”œβ”€β”€ index.html # HTML template β”‚ β”œβ”€β”€ vite.config.ts # Vite configuration β”‚ β”œβ”€β”€ tsconfig.json # TypeScript configuration β”‚ └── package.json # Frontend dependencies β”œβ”€β”€ content/ # Content files (Overview.json, ReleaseNotes.json) β”œβ”€β”€ docs/ # Documentation (PRD, tech stack) β”œβ”€β”€ .env # Environment variables (not in git) β”œβ”€β”€ .env.example # Example environment file β”œβ”€β”€ Dockerfile # Production Docker image β”œβ”€β”€ package.json # Root package configuration └── README.md ``` ### Available Scripts ```bash # Development npm run dev # Start both frontend and backend in dev mode npm run dev:backend # Start backend development server only npm run dev:frontend # Start frontend development server only # Building npm run build # Build both frontend and backend for production npm run build:backend # Build backend only npm run build:frontend # Build frontend only # Production npm start # Start production backend server (after build) # Testing cd src/backend npm test # Run all tests once npm run test:watch # Run tests in watch mode npm run test:ui # Open Vitest UI dashboard npm run test:coverage # Run tests with coverage report # Code Quality npm run lint # Lint both frontend and backend npm run lint:fix # Fix linting issues npm run format # Format code with Prettier # Utilities npm run clean # Clean build artifacts npm run install:all # Install all dependencies (root + backend + frontend) ``` ### Technology Stack **Backend:** - Express.js 5.x with TypeScript - @maxmind/geoip2-node 6.x - GeoIP database reader - node-cache - In-memory caching - express-rate-limit 8.x - Rate limiting - helmet - Security headers - joi - Request validation - seq-logging - Optional structured logging - **tsup** - Modern bundler for fast builds (88ms vs ~1000ms with tsc) ⚑ **Frontend:** - React 19.x with TypeScript - Vite 7.x - Build tool and dev server - Leaflet & react-leaflet - Interactive maps - Axios - HTTP client - OpenStreetMap - Map tiles **Development Tools:** - TypeScript 5.x - ESLint & Prettier - nodemon - Auto-restart on changes - tsx - TypeScript execution **Testing (100% Pass Rate):** - Vitest 3.x - Modern testing framework with ESM support - Supertest - HTTP assertion library for API testing (no port conflicts) - @vitest/ui - Visual test dashboard - @vitest/coverage-v8 - Code coverage reporting - 43 tests (25 integration + 18 unit) - All passing **Build System:** - **tsup** (backend) - esbuild-based bundler with ESM support, no `.js` extensions needed - **Vite** (frontend) - Lightning-fast HMR and optimized production builds > πŸ“– See [tsup Migration Guide](docs/tsup-migration.md) for details on the modern build system. ### Architecture Highlights **App Factory Pattern** - Production-ready architecture with clean separation: - **[src/backend/app.ts](src/backend/app.ts)** - Creates Express app without starting server (for testing) - **[src/backend/server.ts](src/backend/server.ts)** - HTTP server startup with graceful shutdown - **[src/backend/index.ts](src/backend/index.ts)** - Entry point with backward compatibility **Benefits:** - βœ… **Testable** - App can be instantiated without port binding (eliminates test conflicts) - βœ… **Modular** - Clean separation of concerns (app setup vs server lifecycle) - βœ… **Production-Ready** - Industry-standard pattern used in professional applications - βœ… **Fast Tests** - All 43 tests run in ~1 second using Supertest in-memory testing ## βš™οΈ Configuration ### Environment Variables | Variable | Default | Description | | -------------------------- | ---------------------- | ----------------------------------------------------- | | `PORT` | `5172` | Server port | | `BASE_PATH` | `/` | Application base path | | `NODE_ENV` | `development` | Environment mode (development/production) | | `ENABLE_HTTPS_SECURITY` | `false` | Enable HTTPS security headers (CSP, HSTS, COOP, CORP) | | `MAXMIND_DB_PATH` | `/usr/share/maxmind` | MaxMind database directory | | `FRONTEND_API_KEY` | `frontend-default-key` | Frontend API key | | `EXTERNAL_API_KEYS` | `external-default-key` | External API keys (comma-separated) | | `FRONTEND_ALLOWED_ORIGINS` | `http://localhost:*` | Allowed CORS origins for frontend (comma-separated) | | `FRONTEND_RATE_WINDOW_MS` | `60000` | Frontend rate limit window (milliseconds) | | `FRONTEND_RATE_MAX` | `30` | Frontend rate limit max requests | | `EXTERNAL_RATE_WINDOW_MS` | `60000` | External rate limit window (milliseconds) | | `EXTERNAL_RATE_MAX` | `1000` | External rate limit max requests | | `BATCH_LIMIT` | `100` | Maximum IPs per batch request | | `DEBOUNCE_MS` | `2000` | Frontend input debounce delay (milliseconds) | | `SEQ_URL` | - | Seq logging server URL (optional) | | `SEQ_API_KEY` | - | Seq API key (optional) | ### MaxMind Database Setup The service requires both MaxMind GeoLite2-City and GeoLite2-ASN databases. You have two options: **Option 1: Manual Download** 1. Sign up at https://www.maxmind.com/en/geolite2/signup 2. Download both databases (`.mmdb` files): - GeoLite2-City.mmdb - GeoLite2-ASN.mmdb 3. Place them in the same directory (e.g., `D:\tools\maxmind-dbs` on Windows) 4. Set `MAXMIND_DB_PATH` environment variable to that directory **Option 2: Using geoipupdate (Production)** - Use the provided `docker-compose.yml` which includes geoipupdate service - geoipupdate automatically downloads and updates both databases - Both services share a Docker volume for database access ### Rate Limiting Bitip implements different rate limiting for frontend and external API consumers: - **Frontend**: More restrictive limits for web UI usage (default: 100 req/min) - **External**: Higher limits for programmatic API access (default: 1000 req/min) Rate limits are fully configurable via environment variables and include standard HTTP headers in responses. ### HTTPS Security Headers The `ENABLE_HTTPS_SECURITY` variable controls security headers provided by Helmet: - **`false` (default)**: Disables CSP, HSTS, COOP, and CORP headers - required for HTTP deployments - **`true`**: Enables all security headers - use when deploying behind HTTPS reverse proxy (nginx, Traefik, etc.) **Important**: If running on plain HTTP without a reverse proxy, keep this set to `false`. Browser security policies will block resources if HTTPS security headers are enabled on HTTP connections. ## 🐳 Docker Deployment ### Production Setup The service is designed to run alongside MaxMind's geoipupdate service: ```bash # Start both services docker-compose up -d # View logs docker-compose logs -f bitip # Stop services docker-compose down ``` The `docker-compose.yml` includes: - **geoipupdate**: Downloads and updates MaxMind databases - **bitip**: Main application server (API + Web UI) - **Shared volume**: For database access between services ### Health Monitoring The service includes comprehensive health checks: - Docker health check endpoint: `/api/health` - Database connectivity verification - Service status monitoring ## πŸ”§ Troubleshooting ### Common Issues **1. Database Not Found** - Ensure both databases are downloaded to the path specified in `MAXMIND_DB_PATH` - Check that both `GeoLite2-City.mmdb` and `GeoLite2-ASN.mmdb` files exist in that directory - Verify file permissions (read access required) **2. TypeScript Errors** - Run `npm run install:all` to ensure all dependencies are installed - Check that Node.js version is >= 18.0.0 - Try deleting `node_modules` and reinstalling **3. API Authentication Errors** - Verify API key in `.env` file matches the one you're using - Check `X-API-Key` header or `apikey` query parameter format - Ensure API key doesn't contain extra spaces **4. Rate Limiting** - Check rate limit headers in API responses (`X-RateLimit-*`) - Adjust rate limiting configuration if needed - Use external API keys for higher limits **5. Map Display Issues** - Verify internet connectivity for OpenStreetMap tiles - Check browser console for JavaScript errors - Ensure Leaflet CSS is loading correctly **6. Port Already in Use** - Frontend dev server will auto-increment port (5173, 5174, etc.) - Backend port can be changed via `PORT` environment variable - Check for other services using the same ports **7. Test Failures** - All 43 tests should pass (100% success rate) - Run tests: `cd src/backend && npm test` - Check for environment variables in [src/backend/vitest.config.ts](src/backend/vitest.config.ts#L7) - Ensure MaxMind databases are accessible at MAXMIND_DB_PATH ### Logs and Debugging - Application logs are printed to console - Use `npm run dev` for detailed development logs - Configure Seq integration for structured logging - Docker logs: `docker-compose logs -f bitip` ### Running Tests Backend includes comprehensive automated test suite: ```bash # Navigate to backend directory cd src/backend # Run all tests once npm test # Watch mode for development npm run test:watch # Visual UI dashboard npm run test:ui # Generate coverage report npm run test:coverage ``` **Test Results:** - βœ… 43/43 tests passing (100%) - ⚑ Runs in ~1 second - πŸ“Š 25 integration + 18 unit tests - πŸ” Coverage reports in coverage/ folder ## πŸ“¦ Package Versions **Current versions (as of project creation):** - Major packages are on stable versions but not latest - Consider updating for newer features and security fixes - Check `npm outdated` for available updates - Test thoroughly after major version updates **Key outdated packages:** - Express 4.x (5.x available but still beta) - React 18.x (19.x available) - Vite 4.x (7.x available - major update) - Many dev dependencies have newer versions ## πŸ“„ License **Copyright Β© 2025 Tudor Stanciu. All rights reserved.** This software is **proprietary** and confidential. Unauthorized use, copying, modification, distribution, or reverse engineering of this software, in whole or in part, is strictly prohibited without explicit written permission from the copyright holder. ### License Summary - βœ… **Evaluation Period**: 30-day trial for evaluation purposes - βœ… **Approved Use**: Requires explicit written approval from Tudor Stanciu - ❌ **No Redistribution**: Cannot be distributed, sublicensed, or transferred to third parties - ❌ **No Modification**: Cannot be modified or create derivative works without permission - ❌ **No Commercial Use**: Cannot be used for commercial services without separate license ### Obtaining a License For licensing inquiries, commercial use, or approval requests: **Contact**: Tudor Stanciu **Email**: tudor.stanciu94@gmail.com Please include: - Intended use case - Organization name and size - Expected deployment scale - Duration of use See [LICENSE](LICENSE) file for complete terms and conditions. ## πŸ™ Acknowledgments - **MaxMind** for providing GeoLite2 databases - **OpenStreetMap** for map tiles - **Leaflet** for interactive mapping - All open-source contributors --- **Bitip** - Professional GeoIP Lookup Service 🌍 Built with ❀️ using Express.js, React, and MaxMind GeoLite2