query other ip
This commit is contained in:
@@ -48,7 +48,7 @@ jobs:
|
||||
docker push ${{ env.IMAGE_PATH }}:${{ matrix.arch }}-latest
|
||||
|
||||
amend-manifest:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: linux
|
||||
needs: [build]
|
||||
steps:
|
||||
- name: Login to Docker Registry
|
||||
|
||||
265
README.md
Normal file
265
README.md
Normal file
@@ -0,0 +1,265 @@
|
||||
# IP Info Service
|
||||
|
||||
A high-performance IP geolocation service built with Go that provides detailed information about IP addresses including country, ASN (Autonomous System Number), and other geolocation data.
|
||||
|
||||
## Features
|
||||
|
||||
- 🌍 IP geolocation lookup with country information
|
||||
- 🏢 ASN (Autonomous System Number) information
|
||||
- 🚀 High-performance HTTP API
|
||||
- 🔄 Automatic database updates
|
||||
- 🐳 Docker support
|
||||
- 📊 Metrics endpoint for monitoring
|
||||
- 🛡️ Input validation and error handling
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Using Docker (Recommended)
|
||||
|
||||
1. Clone the repository:
|
||||
```bash
|
||||
git clone <repository-url>
|
||||
cd ip-info
|
||||
```
|
||||
|
||||
2. Start the service using Docker Compose:
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
The service will be available at `http://localhost:28080`
|
||||
|
||||
### Manual Installation
|
||||
|
||||
1. Install Go 1.22 or later
|
||||
2. Clone and build:
|
||||
```bash
|
||||
git clone <repository-url>
|
||||
cd ip-info
|
||||
go mod download
|
||||
go build -o ip-info
|
||||
./ip-info
|
||||
```
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### 1. Get Your IP Information
|
||||
|
||||
**Plain Text Response:**
|
||||
```bash
|
||||
curl http://localhost:28080/
|
||||
# Returns: 192.168.1.100
|
||||
```
|
||||
|
||||
**JSON Response:**
|
||||
```bash
|
||||
curl http://localhost:28080/json
|
||||
```
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"ip": "192.168.1.100",
|
||||
"country": "US",
|
||||
"country_name": "United States",
|
||||
"asn": "AS15169",
|
||||
"asn_org": "Google LLC"
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Look Up Specific IP Address
|
||||
|
||||
**Query any IP address:**
|
||||
```bash
|
||||
curl http://localhost:28080/8.8.8.8
|
||||
```
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"ip": "8.8.8.8",
|
||||
"country": "US",
|
||||
"country_name": "United States",
|
||||
"asn": "AS15169",
|
||||
"asn_org": "Google LLC"
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Metrics Endpoint
|
||||
|
||||
Monitor service health and performance:
|
||||
```bash
|
||||
curl http://localhost:28080/metrics
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Environment Variables
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `API_PORT` | `8080` | Port for the HTTP server |
|
||||
| `GIN_TRUSTED_PROXY_IP` | - | Trusted proxy IP for client IP detection |
|
||||
| `GIN_MODE` | `debug` | Gin framework mode (`debug`, `release`) |
|
||||
|
||||
### Using .env File
|
||||
|
||||
Create a `.env` file in the project root:
|
||||
```env
|
||||
API_PORT=8080
|
||||
GIN_TRUSTED_PROXY_IP=127.0.0.1
|
||||
GIN_MODE=release
|
||||
```
|
||||
|
||||
## Docker Configuration
|
||||
|
||||
### Docker Compose
|
||||
|
||||
The included `docker-compose.yml` provides:
|
||||
- Service on port 28080 (maps to container port 8080)
|
||||
- Persistent cache volume
|
||||
- Auto-restart policy
|
||||
- Vietnam timezone configuration
|
||||
|
||||
### Custom Docker Build
|
||||
|
||||
```bash
|
||||
# Build image
|
||||
docker build -t ip-info .
|
||||
|
||||
# Run container
|
||||
docker run -p 8080:8080 -v $(pwd)/.cache:/app/.cache ip-info
|
||||
```
|
||||
|
||||
## Data Sources
|
||||
|
||||
The service automatically downloads and updates IP geolocation databases from:
|
||||
- **Country Data**: GeoLite2 Country database via jsDelivr CDN
|
||||
- **ASN Data**: GeoLite2 ASN database via jsDelivr CDN
|
||||
|
||||
Database updates happen automatically in the background to ensure data freshness.
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Basic IP Lookup
|
||||
```bash
|
||||
# Get information about Google's DNS
|
||||
curl http://localhost:28080/8.8.8.8
|
||||
|
||||
# Get information about Cloudflare's DNS
|
||||
curl http://localhost:28080/1.1.1.1
|
||||
|
||||
# Get your own IP info
|
||||
curl http://localhost:28080/json
|
||||
```
|
||||
|
||||
### Integration Examples
|
||||
|
||||
**JavaScript/Node.js:**
|
||||
```javascript
|
||||
const response = await fetch('http://localhost:28080/8.8.8.8');
|
||||
const ipInfo = await response.json();
|
||||
console.log(ipInfo);
|
||||
```
|
||||
|
||||
**Python:**
|
||||
```python
|
||||
import requests
|
||||
|
||||
response = requests.get('http://localhost:28080/8.8.8.8')
|
||||
ip_info = response.json()
|
||||
print(ip_info)
|
||||
```
|
||||
|
||||
**cURL with jq:**
|
||||
```bash
|
||||
curl -s http://localhost:28080/8.8.8.8 | jq .
|
||||
```
|
||||
|
||||
## Response Format
|
||||
|
||||
All JSON responses include:
|
||||
- `ip`: The queried IP address
|
||||
- `country`: ISO 3166-1 alpha-2 country code
|
||||
- `country_name`: Full country name
|
||||
- `asn`: Autonomous System Number (when available)
|
||||
- `asn_org`: ASN organization name (when available)
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Invalid IP Address
|
||||
```bash
|
||||
curl http://localhost:28080/invalid-ip
|
||||
```
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"error": "invalid ip"
|
||||
}
|
||||
```
|
||||
|
||||
### Service Unavailable
|
||||
If the database is not loaded yet:
|
||||
```
|
||||
HTTP 500: Try again later
|
||||
```
|
||||
|
||||
## Performance
|
||||
|
||||
- **Startup Time**: Database loads automatically on startup
|
||||
- **Response Time**: Sub-millisecond IP lookups after database load
|
||||
- **Memory Usage**: Optimized MMDB format for efficient memory usage
|
||||
- **Concurrency**: Built with Go's excellent concurrency support
|
||||
|
||||
## Monitoring
|
||||
|
||||
### Health Check
|
||||
```bash
|
||||
curl http://localhost:28080/metrics
|
||||
```
|
||||
|
||||
### Logs
|
||||
The service provides structured JSON logging with different log levels. In Docker:
|
||||
```bash
|
||||
docker-compose logs -f ip-info
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
### Local Development
|
||||
```bash
|
||||
# Install dependencies
|
||||
go mod download
|
||||
|
||||
# Run in development mode
|
||||
go run main.go
|
||||
|
||||
# Build for production
|
||||
go build -o ip-info
|
||||
```
|
||||
|
||||
### Project Structure
|
||||
```
|
||||
├── main.go # Application entry point
|
||||
├── configs/ # Configuration files
|
||||
├── internal/
|
||||
│ ├── data/ # Database handling
|
||||
│ └── services/
|
||||
│ ├── api/ # HTTP API handlers
|
||||
│ └── db_updater/ # Database update service
|
||||
├── pkg/ # Shared packages
|
||||
├── data/ # Database files (auto-generated)
|
||||
└── docker-compose.yml # Docker configuration
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
[Add your license information here]
|
||||
|
||||
## Contributing
|
||||
|
||||
[Add contribution guidelines here]
|
||||
|
||||
## Support
|
||||
|
||||
For issues and questions, please [open an issue](link-to-issues) or contact the maintainers.
|
||||
@@ -5,6 +5,6 @@ import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func HandleIp(c *gin.Context) {
|
||||
func HandleMyIp(c *gin.Context) {
|
||||
c.String(http.StatusOK, c.ClientIP())
|
||||
}
|
||||
|
||||
@@ -3,12 +3,26 @@ package api
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/rs/zerolog/log"
|
||||
"net"
|
||||
"net/http"
|
||||
"thuanle.me/ip-info/internal/data"
|
||||
)
|
||||
|
||||
func HandleJson(c *gin.Context) {
|
||||
ip := c.ClientIP()
|
||||
HandleIpInfo(c, ip)
|
||||
}
|
||||
|
||||
func HandleOtherIp(c *gin.Context) {
|
||||
ip := c.Param("ip")
|
||||
if net.ParseIP(ip) == nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid ip"})
|
||||
return
|
||||
}
|
||||
HandleIpInfo(c, ip)
|
||||
}
|
||||
|
||||
func HandleIpInfo(c *gin.Context, ip string) {
|
||||
if !data.Ins().IsLoaded() {
|
||||
log.Error().Msg("DB is not loaded")
|
||||
c.String(http.StatusInternalServerError, "Try again later")
|
||||
@@ -26,5 +40,4 @@ func HandleJson(c *gin.Context) {
|
||||
|
||||
ipData["ip"] = ip
|
||||
c.JSON(http.StatusOK, ipData)
|
||||
|
||||
}
|
||||
|
||||
@@ -22,9 +22,10 @@ func StartApiService() {
|
||||
_ = engine.SetTrustedProxies([]string{trustedProxyIP})
|
||||
}
|
||||
|
||||
engine.GET("/", HandleIp)
|
||||
engine.GET("/", HandleMyIp)
|
||||
engine.GET("/json", HandleJson)
|
||||
engine.GET("/metrics", HandleMetrics)
|
||||
engine.GET("/:ip", HandleOtherIp)
|
||||
|
||||
port := os.Getenv(key.EnvApiPort)
|
||||
if len(port) == 0 {
|
||||
|
||||
Reference in New Issue
Block a user