bitip/README.md
Tudor Stanciu 9ad0d9be93 feat: update version to 1.2.0 and refactor backend structure
- Changed main entry point from `index.js` to `server.js` in package.json.
- Created a new `app.ts` file to encapsulate Express app configuration.
- Removed old `index.ts` file and moved server logic to `server.ts`.
- Updated nodemon configurations to point to the new `server.ts`.
- Added new middleware for API key authentication with public endpoint support.
- Modified validators to accept any string for IPs, allowing handlers to determine validity.
- Added integration tests for batch lookup and health endpoints.
- Implemented unit tests for error handling and validation middleware.
- Updated `tsup` and `vitest` configurations to reflect new entry points and testing setup.
2025-10-13 01:14:37 +03:00

691 lines
21 KiB
Markdown

# 🌍 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<IpLocation> 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 <repository-url>
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