Skip to content

Latest commit

 

History

History
465 lines (422 loc) · 11.7 KB

File metadata and controls

465 lines (422 loc) · 11.7 KB

🖧 HostInfo API Documentation

The HostInfo API provides endpoints for retrieving system information and performing network diagnostics such as ping, DNS lookup, HTTP requests, and TCP port checks. All endpoints are served under /api/v1/.

All responses are in JSON format. Errors automatically return an error field.

Base URL

http://<host>:<port>/api/v1/
  • Default host: 0.0.0.0
  • Default port: 8080
  • Health check: /healthz (outside API)

Request Flow Diagram (High-Level):

┌──────────┐
│  Client  │
│ (curl)   │
└────┬─────┘
     │ HTTP Request
     ▼
┌──────────────┐
│  HTTP Router │
│ (chi / mux)  │
└────┬─────────┘
     │
     ▼
┌────────────────────┐
│ Rate Limit Middleware │
│  - Per IP limiter     │
│  - Token bucket       │
│  - Burst support      │
└────┬─────────────────┘
     │
     ├─❌ Limit exceeded
     │    └─► 429 JSON + X-RateLimit headers
     │
     ▼
┌──────────────┐
│ API Handler  │
│ (ping/dns/…) │
└────┬─────────┘
     │
     ▼
┌──────────────┐
│ JSON Response│
└──────────────┘

Rate Limiting

All API endpoints are protected by rate limiting per IP to prevent spam:

  • Default: 15 requests per minute per IP, burst 5 requests.

  • Exceeding the limit returns HTTP 429:

    {
      "error": "rate limit exceeded"
    }
  • Standard headers returned for all requests:

    Header Description
    X-RateLimit-Limit Maximum allowed requests per minute (burst)
    X-RateLimit-Remaining Number of requests left in the current window
    X-RateLimit-Reset Unix timestamp when the next token will be available

    Example curl to see headers:

    curl -s -D - "http://localhost:8080/api/v1/ping?host=google.com" -o /dev/null

    Output:

    HTTP/1.1 200 OK
    X-RateLimit-Limit: 5
    X-RateLimit-Remaining: 4
    X-RateLimit-Reset: 1674928370
    Content-Type: application/json

Example Response When Rate Limited

HTTP/1.1 429 Too Many Requests
Content-Type: application/json
X-RateLimit-Limit: 5
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1674928370

{"error":"rate limit exceeded"}

Configurable via: internal/api/middleware/rate_limiter.go

var (
    rateLimit = rate.Every(time.Minute / 15) // 15 req/min
    burst     = 5                            // allow bursts
)

Rate Limiter Internals (Detailed):

              ┌─────────────────────┐
              │ Incoming Request IP │
              └─────────┬───────────┘
                        ▼
           ┌──────────────────────────┐
           │ clients[ip] lookup       │
           │ map[string]*client       │
           └─────────┬────────────────┘
                     │
        ┌────────────▼────────────┐
        │ Exists?                  │
        └──────┬──────────┬───────┘
               │ yes      │ no
               │          ▼
               │   ┌────────────────┐
               │   │ Create limiter │
               │   │ rate + burst   │
               │   │ lastSeen=now   │
               │   └────────────────┘
               ▼
┌──────────────────────────┐
│ limiter.Allow()          │
│ (token bucket algorithm)│
└─────────┬────────────────┘
          │
   ┌──────▼──────┐
   │ Allowed?    │
   └───┬────┬───┘
       │yes │no
       │    ▼
       │  429 Too Many Requests
       │  + X-RateLimit headers
       ▼
┌──────────────────────────┐
│ Update headers:          │
│ - Limit                  │
│ - Remaining              │
│ - Reset                  │
└─────────┬────────────────┘
          ▼
┌──────────────────────────┐
│ Forward to API handler   │
└──────────────────────────┘

Cleanup Goroutine (Optional Diagram):

┌────────────────────────────┐
│ Background Cleanup Loop    │
│ (every 5 minutes)          │
└─────────┬──────────────────┘
          ▼
┌────────────────────────────┐
│ Iterate clients map        │
└─────────┬──────────────────┘
          ▼
┌────────────────────────────┐
│ lastSeen > TTL ?           │
└──────┬────────────┬────────┘
       │ yes        │ no
       ▼            ▼
 Delete limiter   Keep client

Endpoints

1. Health Check

Health endpoints are exposed outside /api/v1 and are intended for:

  • Kubernetes probes

  • Load balancers

  • Simple service monitoring

1.1 Combined Health Check

GET /healthz

Description: High-level health endpoint combining liveness and readiness checks. Useful for manual checks and simple monitoring tools.

Response:

{ "status": "ok" }

Example:

curl -s http://localhost:8080/healthz | jq

1.2 Liveness Probe

GET /healthz/live

Description: Indicates whether the application process is running.

Response:

{ "status": "ok" }

Example:

curl -s http://localhost:8080/healthz/live | jq

1.3 Readiness Probe

GET /healthz/ready

Description: Indicates whether the application is ready to receive traffic (e.g. dependencies initialized, not shutting down).

Response:

{
  "status": "ok",
  "checks": {
    "uptime": "24.381354968s"
  }
}

Example:

curl -s http://localhost:8080/healthz/ready | jq

2. Ping

GET /api/v1/ping?host=<hostname>

Description: Ping a host to check availability and latency.

Query Parameters:

Parameter Type Required Description
host string Yes Hostname or IP to ping

Response:

{
  "host": "google.com",
  "packets_sent": 3,
  "packets_recv": 3,
  "loss_percent": 0,
  "min_rtt": "12.345ms",
  "max_rtt": "14.678ms",
  "avg_rtt": "13.456ms"
}

Error Response Example:

{"error":"host parameter required"}

Curl Example:

curl -s "http://localhost:8080/api/v1/ping?host=google.com" | jq

3. DNS Lookup

GET /api/v1/dns?host=<hostname>

Description: Resolve a hostname to its IP addresses and CNAME.

Query Parameters:

Parameter Type Required Description
host string Yes Hostname to resolve

Response:

{
  "host": "google.com",
  "ips": ["142.250.72.238", "142.250.72.206"],
  "cname": "google.com."
}

Curl Example:

curl -s "http://localhost:8080/api/v1/dns?host=google.com" | jq

4. HTTP Request / Curl

GET /api/v1/curl?url=<url>

Description: Perform an HTTP GET request and return status and body.

Query Parameters:

Parameter Type Required Description
url string Yes URL to fetch

Response:

{
  "url": "https://google.com",
  "status_code": 200,
  "body": "<!doctype html>...."
}

Error Response Example:

{"error":"Get \"https://nonexistent.site\": dial tcp: lookup nonexistent.site: no such host"}

Curl Example:

curl -s "http://localhost:8080/api/v1/curl?url=https://google.com" | jq

5. TCP Port Check

GET /api/v1/tcp?host=<host>&port=<port>

Description: Check if a TCP port is open on a given host.

Query Parameters:

Parameter Type Required Description
host string Yes Hostname or IP
port string Yes Port number

Response:

{
  "host": "google.com",
  "port": "80",
  "open": true
}

Error Response Example:

{
  "host": "google.com",
  "port": "801",
  "open": false,
  "error": "dial tcp 142.251.98.113:801: i/o timeout"
}

Curl Example:

curl -s "http://localhost:8080/api/v1/tcp?host=google.com&port=80" | jq

6. Host Information

GET /api/v1/info

Description: Returns general system and runtime information about the host where the service is running.

Response:

{
  "hostname": "host-name",
  "ips": [
    "192.168.1.1",
    "192.168.12.12",
    "192.168.13.13"
  ],
  "macs": [
    "62:55:44:22:g8:10",
    "72:35:34:04:d4:10"
  ],
  "os": "darwin",
  "arch": "amd64",
  "goVersion": "go1.24.12",
  "startTime": "2026-01-28T21:31:12+02:00",
  "now": "2026-01-28T21:36:14+02:00",
  "env": {
    "COLORTERM": "truecolor",
    "COMMAND_MODE": "unix2003"
  },
  "cloud": {
    "provider": "local",
    "region": "",
    "zone": "",
    "instance": "",
    "extra": null
  },
  "kubernetes": {
    "enabled": false,
    "podName": "",
    "podNamespace": "",
    "podIP": "",
    "nodeName": "",
    "serviceAccount": "",
    "container": ""
  }
}

Error Response Example:

{ "error": "failed to collect host info" }

Curl Example:

curl -s "http://localhost:8080/api/v1/info" | jq

7. Cloud Provider Detection

GET /api/v1/cloud

Description: Detects whether the service is running in a supported cloud provider and returns cloud metadata.

Response:

{
  "provider": "local",
  "region": "",
  "zone": "",
  "instance": "",
  "extra": null
}

Response (Not in Cloud):

{ "provider": "unknown" }

Error Response Example:

{ "error": "cloud metadata service unavailable" }

Curl Example:

curl -s "http://localhost:8080/api/v1/cloud" | jq

8. Kubernetes Environment Info

GET /api/v1/kubernetes

Description: Detects whether the application is running inside a Kubernetes cluster and returns pod-level metadata.

Response:

{
  "enabled": false,
  "podName": "",
  "podNamespace": "",
  "podIP": "",
  "nodeName": "",
  "serviceAccount": "",
  "container": ""
}

Error Response Example:

{ "error": "kubernetes API not accessible" }

Curl Example:

curl -s "http://localhost:8080/api/v1/kubernetes" | jq

Notes / Best Practices

  • All endpoints return JSON. If a parameter is missing or invalid, the response contains an error field.

  • Use jq for pretty-printing JSON responses:

    curl -s "http://localhost:8080/api/v1/ping?host=google.com" | jq
  • Endpoints are designed for network diagnostics and monitoring. Avoid running intensive requests in high frequency on external hosts.