query other ip
This commit is contained in:
@@ -48,7 +48,7 @@ jobs:
|
|||||||
docker push ${{ env.IMAGE_PATH }}:${{ matrix.arch }}-latest
|
docker push ${{ env.IMAGE_PATH }}:${{ matrix.arch }}-latest
|
||||||
|
|
||||||
amend-manifest:
|
amend-manifest:
|
||||||
runs-on: ubuntu-latest
|
runs-on: linux
|
||||||
needs: [build]
|
needs: [build]
|
||||||
steps:
|
steps:
|
||||||
- name: Login to Docker Registry
|
- 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"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func HandleIp(c *gin.Context) {
|
func HandleMyIp(c *gin.Context) {
|
||||||
c.String(http.StatusOK, c.ClientIP())
|
c.String(http.StatusOK, c.ClientIP())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,12 +3,26 @@ package api
|
|||||||
import (
|
import (
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"thuanle.me/ip-info/internal/data"
|
"thuanle.me/ip-info/internal/data"
|
||||||
)
|
)
|
||||||
|
|
||||||
func HandleJson(c *gin.Context) {
|
func HandleJson(c *gin.Context) {
|
||||||
ip := c.ClientIP()
|
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() {
|
if !data.Ins().IsLoaded() {
|
||||||
log.Error().Msg("DB is not loaded")
|
log.Error().Msg("DB is not loaded")
|
||||||
c.String(http.StatusInternalServerError, "Try again later")
|
c.String(http.StatusInternalServerError, "Try again later")
|
||||||
@@ -26,5 +40,4 @@ func HandleJson(c *gin.Context) {
|
|||||||
|
|
||||||
ipData["ip"] = ip
|
ipData["ip"] = ip
|
||||||
c.JSON(http.StatusOK, ipData)
|
c.JSON(http.StatusOK, ipData)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,9 +22,10 @@ func StartApiService() {
|
|||||||
_ = engine.SetTrustedProxies([]string{trustedProxyIP})
|
_ = engine.SetTrustedProxies([]string{trustedProxyIP})
|
||||||
}
|
}
|
||||||
|
|
||||||
engine.GET("/", HandleIp)
|
engine.GET("/", HandleMyIp)
|
||||||
engine.GET("/json", HandleJson)
|
engine.GET("/json", HandleJson)
|
||||||
engine.GET("/metrics", HandleMetrics)
|
engine.GET("/metrics", HandleMetrics)
|
||||||
|
engine.GET("/:ip", HandleOtherIp)
|
||||||
|
|
||||||
port := os.Getenv(key.EnvApiPort)
|
port := os.Getenv(key.EnvApiPort)
|
||||||
if len(port) == 0 {
|
if len(port) == 0 {
|
||||||
|
|||||||
Reference in New Issue
Block a user