Files
zhiqiang feng ce4c2b088f fix: comprehensive bug fixes, hardening, and test coverage
Bug fixes:
- Fix nil-pointer panic in sendMessage SOAP fault handler (used err.Error() on nil)
- Fix missing return after SOAP fault response (caused fall-through to 200 OK)
- Fix timeout=0 shadowing: removed package-level constant, use configured value
- Fix receiveMessage not checking SOAP faults from CIIMS

Codec hardening:
- Replace fragile regex parsing with encoding/xml.Decoder for namespace-agnostic XML
- XML-escape all user inputs (user, pass, event) — not just message body
- Remove magic-number-based string slicing (split, GetErrMsg)

Transport improvements:
- Extract Client type with connection pooling (reuse http.Client across requests)
- Add CIIMSResponse domain type with IsFault(), ErrorMessage(), Messages()
- Add HTTPStatusError and ResponseTooLargeError typed errors
- Replace deprecated ioutil.ReadAll with io.ReadAll
- Add response body size limit (64 MiB)

Security hardening:
- Add MaxBytesReader (1MB request body limit) on both endpoints
- Add URL allowlist via CIIMS_ALLOWED_SERVERS env var
- Add normalizeBaseURL with scheme/host/query validation
- Add count bounds validation (1-1000) on /receive
- Add server-level timeouts (ReadHeaderTimeout, ReadTimeout, IdleTimeout)

Configuration:
- Introduce Config struct to replace package-level globals
- Add loadConfig() with full validation and error propagation
- Add getIntEnv() with positive-value enforcement

Test coverage (75 tests, 35 new):
- Phase 1: 8 internal tests (nil receiver, error types, SOAP+HTTP500, malformed XML)
- Phase 2: 19 pure function tests (normalizeBaseURL, parseAllowedServers, getIntEnv)
- Phase 3: 16 handler tests (send/receive success, SOAP fault, network error, HTTP 500,
  body too large, invalid JSON, missing fields, URL allowlist)
- Phase 4: 8 config/router tests (loadConfig, newServer, newRouter)

Toolchain:
- Upgrade Go 1.13 → 1.22, gin 1.6.3 → 1.10.0, testify 1.5.1 → 1.10.0

Cleanup:
- Remove dead code (unused post() function, commented-out defaults)
- Replace println with structured logging
- Add .gitignore
- Rewrite README with API docs, env vars, security considerations
2026-07-08 16:23:00 +08:00

2.7 KiB

CIIMS web service message exchange proxy

A thin HTTP proxy that translates JSON POST requests into SOAP/XML calls to a CIIMS ExchangeService backend. Designed for airport operational message exchange (AODB/FLOP).

API

POST /send

Send a message to CIIMS.

Request body (JSON):

{
    "url":     "http://domain.tld",   // optional, overrides CIIMS_SERVER
    "user":    "ciims username",      // required
    "pass":    "ciims password",      // required
    "event":   "route event id",      // required
    "priority": 0,                    // optional, defaults to 0
    "val":     false,                 // optional, defaults to false
    "msg":     "ciims xml body"       // required
}

POST /receive

Receive messages from CIIMS.

Request body (JSON):

{
    "url":   "http://domain.tld",   // optional, overrides CIIMS_SERVER
    "user":  "ciims username",      // required
    "pass":  "ciims password",      // required
    "count": 3                      // required, 1-1000
}

GET /ping

Health check — returns {"message": "pong"}.

Configuration

Environment Variable Description Default
CIIMS_SERVER Base URL of the default CIIMS ExchangeService (required)
CIIMS_ALLOWED_SERVERS Comma-separated extra CIIMS base URLs allowed for request url overrides empty
PROXY_LISTEN Bind address for the proxy HTTP server :9090
CIIMS_TIMEOUT Outbound request timeout in seconds 240

Security Considerations

  • Authentication: This proxy does not authenticate callers. Deploy behind a firewall or add a reverse-proxy layer (nginx, envoy) with API key / basic auth.
  • TLS: Use a TLS-terminating reverse proxy in production. The proxy itself serves plain HTTP and transmits CIIMS credentials with every request.
  • Input limits: Request bodies are limited to 1 MB, CIIMS responses are limited to 64 MiB, and the count parameter on /receive is capped at 1000.
  • URL overrides: Per-request url values are accepted only when they match CIIMS_SERVER or an entry in CIIMS_ALLOWED_SERVERS after normalization.
  • Credentials: CIIMS usernames and passwords are XML-escaped before being embedded in SOAP envelopes. They are not logged.

Build

go build -o ciimsproxy ./cmd/main/

Example

# Start the proxy
CIIMS_SERVER=http://192.168.1.100:8080 ./ciimsproxy

# Send a message
curl -X POST http://localhost:9090/send \
  -H 'Content-Type: application/json' \
  -d '{"user":"FIMS","pass":"FIMS","event":"FLOP-CHDT","msg":"<MSG/>"}'

# Receive messages
curl -X POST http://localhost:9090/receive \
  -H 'Content-Type: application/json' \
  -d '{"user":"FIMS","pass":"FIMS","count":5}'