{"id":23390687,"url":"https://github.com/philipschmid/echo-app","last_synced_at":"2026-07-01T13:00:26.086Z","repository":{"id":241337549,"uuid":"806614308","full_name":"PhilipSchmid/echo-app","owner":"PhilipSchmid","description":"Tiny golang app that echoes metadata and stats about the request.","archived":false,"fork":false,"pushed_at":"2026-06-22T07:41:46.000Z","size":354,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-06-22T09:27:55.459Z","etag":null,"topics":["demo","docker","echo","go","testing"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PhilipSchmid.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-05-27T14:34:51.000Z","updated_at":"2026-06-22T07:41:50.000Z","dependencies_parsed_at":"2024-12-03T23:22:29.563Z","dependency_job_id":"27fca71b-d2ce-40a7-9525-c5d8707e6f64","html_url":"https://github.com/PhilipSchmid/echo-app","commit_stats":null,"previous_names":["philipschmid/echo-app"],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/PhilipSchmid/echo-app","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PhilipSchmid%2Fecho-app","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PhilipSchmid%2Fecho-app/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PhilipSchmid%2Fecho-app/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PhilipSchmid%2Fecho-app/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PhilipSchmid","download_url":"https://codeload.github.com/PhilipSchmid/echo-app/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PhilipSchmid%2Fecho-app/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35007278,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-01T02:00:05.325Z","response_time":130,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["demo","docker","echo","go","testing"],"created_at":"2024-12-22T03:42:55.690Z","updated_at":"2026-07-01T13:00:26.077Z","avatar_url":"https://github.com/PhilipSchmid.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# echo-app\n\n![CI](https://github.com/philipschmid/echo-app/actions/workflows/ci.yaml/badge.svg) ![Docker Build](https://github.com/philipschmid/echo-app/actions/workflows/docker.yaml/badge.svg) ![Release](https://github.com/philipschmid/echo-app/actions/workflows/release.yaml/badge.svg)\n\nThe `echo-app` is a versatile Go application designed to echo back a JSON payload containing detailed information about incoming requests. It's an invaluable tool for testing, debugging, and understanding network interactions across multiple protocols. The JSON response includes:\n\n- **Timestamp**: When the request was received.\n- **Source IP**: The IP address of the client making the request.\n- **Hostname**: The name of the host running the application.\n- **Listener Name**: The type of listener handling the request (e.g., HTTP, TLS, TCP, gRPC, QUIC).\n- **HTTP Details** (for HTTP, TLS, QUIC listeners): HTTP version, method, endpoint, and optionally request headers.\n- **gRPC Method** (for gRPC listener): The invoked gRPC method name.\n- **Customizable Message**: An optional message to identify specific environments or configurations.\n- **Node Name**: Useful in Kubernetes to identify the node hosting the pod.\n\n## Key Features\n\n- **HTTP Listener**: Serves the JSON payload over HTTP.\n- **TLS (HTTPS) Listener**: Uses an in-memory self-signed certificate for secure HTTPS communication.\n- **QUIC Listener**: Supports HTTP/3 over QUIC with TLS encryption.\n- **TCP Listener**: Provides the JSON payload over a raw TCP connection with connection pooling.\n- **gRPC Listener**: Delivers the same details via a gRPC service with reflection support.\n- **Prometheus Metrics**: Exposes unified request metrics for monitoring.\n\n## Configuration Options\n\n### Environment Variables\nConfigure the application using these environment variables:\n\n- `ECHO_APP_MESSAGE`: A customizable message included in the response. If unset, no message is included.\n- `ECHO_APP_NODE`: The name of the node where the app is running (e.g., for Kubernetes).\n- `ECHO_APP_PORT`: Port for the HTTP server (default: `8080` TCP).\n- `ECHO_APP_PRINT_HTTP_REQUEST_HEADERS`: Set to `true` to include HTTP request headers in the response.\n- `ECHO_APP_H2C`: Set to `true` to enable HTTP/2 cleartext (h2c) on the HTTP listener.\n- `ECHO_APP_TLS`: Set to `true` to enable the TLS (HTTPS) listener.\n- `ECHO_APP_TLS_PORT`: Port for the TLS server (default: `8443` TCP).\n- `ECHO_APP_TCP`: Set to `true` to enable the TCP listener.\n- `ECHO_APP_TCP_PORT`: Port for the TCP server (default: `9090` TCP).\n- `ECHO_APP_GRPC`: Set to `true` to enable the gRPC listener.\n- `ECHO_APP_GRPC_PORT`: Port for the gRPC server (default: `50051` TCP).\n- `ECHO_APP_QUIC`: Set to `true` to enable the QUIC listener.\n- `ECHO_APP_QUIC_PORT`: Port for the QUIC server (default: `4433` UDP).\n- `ECHO_APP_METRICS`: Set to `true` to enable the Prometheus metrics endpoint (default: `true`).\n- `ECHO_APP_METRICS_PORT`: Port for the metrics server (default: `3000` TCP).\n- `ECHO_APP_LOG_LEVEL`: Logging level (`debug`, `info`, `warn`, `error`; default: `info`).\n- `ECHO_APP_MAX_REQUEST_SIZE`: Maximum request body size in bytes (default: `10485760` - 10MB).\n- `ECHO_APP_EXTERNAL_READINESS_PROBE_TYPE`: Optional external readiness probe type: `none`, `http`, `tcp`, or `icmp` (default: `none`).\n- `ECHO_APP_EXTERNAL_READINESS_PROBE_TARGET`: External readiness target, such as `https://api.example.com/ready`, `db.example.com:5432`, or `10.0.0.10`.\n- `ECHO_APP_EXTERNAL_READINESS_PROBE_INTERVAL`: How often the background readiness controller checks the target (default: `10s`).\n- `ECHO_APP_EXTERNAL_READINESS_PROBE_TIMEOUT`: Per-check timeout before the app marks itself not ready (default: `2s`).\n- `ECHO_APP_EXTERNAL_READINESS_HTTP_METHOD`: HTTP method for external HTTP readiness probes (default: `GET`).\n- `ECHO_APP_EXTERNAL_READINESS_HTTP_EXPECTED_STATUS`: Expected HTTP status code for external HTTP readiness probes (default: `200`).\n\n### Command-Line Flags\nRun `./echo-app --help` to see all available flags:\n\n```bash\nUsage of ./echo-app:\n      --external-readiness-http-expected-status int\n                                     Expected HTTP status for external readiness HTTP probes (default 200)\n      --external-readiness-http-method string\n                                     HTTP method for external readiness HTTP probes (default \"GET\")\n      --external-readiness-probe-interval duration\n                                     External readiness probe interval (default 10s)\n      --external-readiness-probe-target string\n                                     External readiness probe target URL, host:port, or host/IP\n      --external-readiness-probe-timeout duration\n                                     External readiness probe timeout (default 2s)\n      --external-readiness-probe-type string\n                                     External readiness probe type: none, http, tcp, or icmp (default \"none\")\n      --grpc                         Enable gRPC server\n      --grpc-port string             gRPC server port (default \"50051\")\n      --http-port string             HTTP server port (default \"8080\")\n      --log-level string             Log level (debug, info, warn, error) (default \"info\")\n      --max-request-size int         Maximum request body size in bytes (default 10485760)\n      --message string               Custom message\n      --metrics                      Enable metrics server (default true)\n      --metrics-port string          Metrics server port (default \"3000\")\n      --node string                  Node name\n      --print-http-request-headers   Print HTTP request headers\n      --quic                         Enable QUIC server\n      --quic-port string             QUIC server port (default \"4433\")\n      --tcp                          Enable TCP server\n      --tcp-port string              TCP server port (default \"9090\")\n      --h2c                          Enable HTTP/2 cleartext (h2c) on the HTTP listener\n      --tls                          Enable TLS server\n      --tls-port string              TLS server port (default \"8443\")\n```\n\n## Quick Start\n\n### Using Make\n```bash\n# Show all available commands\nmake help\n\n# Quick build and run\nmake build-quick \u0026\u0026 make run\n\n# Run with all protocols enabled\nmake run-all\n\n# Run integration tests\nmake test-integration\n```\n\n### Using Docker\n```bash\n# Run with all protocols enabled\ndocker run -it --rm \\\n  -p 8080:8080 -p 8443:8443 -p 9090:9090 \\\n  -p 50051:50051 -p 4433:4433/udp -p 3000:3000 \\\n  -e ECHO_APP_TLS=true \\\n  -e ECHO_APP_TCP=true \\\n  -e ECHO_APP_GRPC=true \\\n  -e ECHO_APP_QUIC=true \\\n  ghcr.io/philipschmid/echo-app:main\n```\n\n## Makefile Targets\n\nThe Makefile has been significantly enhanced with categorized targets and color-coded output:\n\n### Development\n- `make dev` - Run with file watching (requires entr)\n- `make proto` - Generate protobuf files\n- `make deps` - Download and verify dependencies\n- `make tidy` - Tidy and vendor dependencies\n\n### Building\n- `make build` - Build with all checks (lint, vet, test)\n- `make build-quick` - Quick build without checks\n- `make build-all` - Build for all platforms (Linux, macOS, Windows)\n\n### Testing\n- `make test` - Run unit tests with coverage\n- `make test-coverage` - Generate detailed HTML coverage report\n- `make test-short` - Run only short tests\n- `make test-integration` - Run comprehensive integration tests\n- `make benchmark` - Run performance benchmarks\n- `make lint` - Run golangci-lint\n- `make lint-fix` - Run golangci-lint with auto-fix\n- `make check` - Run all checks (lint, vet, test)\n\n### Running\n- `make run` - Run with default settings\n- `make run-all` - Run with all protocol listeners\n- `make run-debug` - Run with debug logging\n- `make run-docker` - Run in Docker container\n\n### Docker\n- `make docker` - Build Docker image for current platform\n- `make docker-multi` - Build multi-platform Docker image\n- `make docker-push` - Push Docker image to registry\n\n### Maintenance\n- `make clean` - Clean build artifacts and test cache\n- `make install` - Install to GOPATH/bin\n- `make info` - Show project information and statistics\n- `make tools` - Install required development tools\n- `make pre-commit` - Run pre-commit checks\n\n## Building the Application\n\n### Local Build\n```bash\n# Full build with all checks\nmake build\n\n# Quick build for development\nmake build-quick\n\n# Cross-platform builds\nmake build-all\n```\n\n### Container Image\n```bash\n# Build for current platform\nmake docker\n\n# Build multi-architecture image (amd64 and arm64)\nmake docker-multi\n```\n\n## Running the Application\n\n### Local Execution\n```bash\n# Start only the HTTP listener\nmake run\n\n# Start all listeners\nmake run-all\n\n# Start with debug logging\nmake run-debug\n\n# Or run directly with specific flags\n./echo-app --tls --tcp --grpc --quic --log-level debug\n```\n\n### Development Mode\n```bash\n# Run with file watching (auto-restart on changes)\nmake dev\n```\n\n## Testing\n\n### Unit Tests\n```bash\n# Run all tests\nmake test\n\n# Generate coverage report\nmake test-coverage\n\n# Run benchmarks\nmake benchmark\n```\n\n### Integration Tests\n```bash\n# Run comprehensive integration tests\nmake test-integration\n```\n\nThis will test:\n- HTTP endpoint with various paths\n- TLS/HTTPS endpoint\n- TCP raw connections\n- gRPC service calls\n- QUIC/HTTP3 (if curl supports it)\n- Prometheus metrics endpoint\n- Health and readiness checks\n- Graceful shutdown behavior\n\n### Manual Testing Examples\n\n#### HTTP Listener\n```bash\ncurl -sS http://localhost:8080/ | jq\n```\n\n**Sample Output**:\n```json\n{\n  \"timestamp\": \"2024-08-06T12:09:46.174+02:00\",\n  \"source_ip\": \"192.168.65.1\",\n  \"hostname\": \"demo-host\",\n  \"listener\": \"HTTP\",\n  \"http_version\": \"HTTP/1.1\",\n  \"http_method\": \"GET\",\n  \"http_endpoint\": \"/\"\n}\n```\n\n#### TLS (HTTPS) Listener\n```bash\ncurl -sSk https://localhost:8443/ | jq\n```\n\n#### TCP Listener\n```bash\necho \"test\" | nc localhost 9090 | jq\n```\n\n#### gRPC Listener\n```bash\ngrpcurl -plaintext -emit-defaults localhost:50051 echo.EchoService.Echo\n```\n\n#### Health Checks\n```bash\n# Health endpoint (liveness): returns 200 only when the echo app process is healthy\ncurl -s http://localhost:3000/health\n# Returns: healthy\n\n# Readiness endpoint: returns 200 only when the echo app is ready and any configured external readiness probe is passing\ncurl -s http://localhost:3000/ready\n# Returns: ready\n\n# Kubernetes probes should use the dedicated metrics/admin listener (default port 3000), not the echo traffic listeners.\n\n# Prometheus metrics\ncurl -s http://localhost:3000/metrics | grep echo_app\n```\n\n#### External Readiness Probe Examples\nThe external readiness probe is optional. When enabled, the app keeps checking the configured target in the background and `/ready` returns `503` until the target succeeds within the configured timeout.\n\n```bash\n# HTTP readiness dependency: expect a 200 from the upstream readiness URL\nECHO_APP_EXTERNAL_READINESS_PROBE_TYPE=http \\\nECHO_APP_EXTERNAL_READINESS_PROBE_TARGET=https://upstream.example.com/ready \\\nECHO_APP_EXTERNAL_READINESS_PROBE_TIMEOUT=2s \\\nECHO_APP_EXTERNAL_READINESS_PROBE_INTERVAL=10s \\\n./echo-app\n\n# TCP readiness dependency: require a connectable host:port\nECHO_APP_EXTERNAL_READINESS_PROBE_TYPE=tcp \\\nECHO_APP_EXTERNAL_READINESS_PROBE_TARGET=db.example.com:5432 \\\n./echo-app\n\n# ICMP readiness dependency: require one successful echo reply within the timeout\nECHO_APP_EXTERNAL_READINESS_PROBE_TYPE=icmp \\\nECHO_APP_EXTERNAL_READINESS_PROBE_TARGET=10.0.0.10 \\\n./echo-app\n```\n\nThe ICMP probe runs in-process and does not require a `ping` binary in the\ncontainer. It uses raw ICMP sockets, so container runtimes that drop\n`CAP_NET_RAW` must add that capability back for ICMP readiness probes.\n\n### Unified Metrics\n\nThe application now exposes unified Prometheus metrics:\n\n```\n# Request metrics\necho_app_requests_total{listener=\"HTTP\",method=\"GET\",endpoint=\"/\"}\necho_app_request_duration_seconds{listener=\"HTTP\",method=\"GET\",endpoint=\"/\"}\n\n# Error metrics\necho_app_errors_total{listener=\"HTTP\",error_type=\"marshal_error\"}\n\n# Connection metrics (for TCP)\necho_app_active_connections{listener=\"TCP\"}\n```\n\n## Kubernetes Deployment\n\nDeploy `echo-app` in Kubernetes with all listeners enabled:\n\n```yaml\n---\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: echo-app-config\ndata:\n  ECHO_APP_MESSAGE: \"demo-env\"\n  ECHO_APP_PRINT_HTTP_REQUEST_HEADERS: \"true\"\n  ECHO_APP_TLS: \"true\"\n  ECHO_APP_QUIC: \"true\"\n  ECHO_APP_GRPC: \"true\"\n  ECHO_APP_TCP: \"true\"\n  ECHO_APP_METRICS: \"true\"\n  # Optional: mark this pod not-ready when a required upstream stops responding.\n  ECHO_APP_EXTERNAL_READINESS_PROBE_TYPE: \"http\"\n  ECHO_APP_EXTERNAL_READINESS_PROBE_TARGET: \"https://upstream.example.com/ready\"\n  ECHO_APP_EXTERNAL_READINESS_HTTP_METHOD: \"GET\"\n  ECHO_APP_EXTERNAL_READINESS_HTTP_EXPECTED_STATUS: \"200\"\n  ECHO_APP_EXTERNAL_READINESS_PROBE_TIMEOUT: \"2s\"\n  ECHO_APP_EXTERNAL_READINESS_PROBE_INTERVAL: \"10s\"\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: echo-app-deployment\n  labels:\n    app: echo-app\nspec:\n  replicas: 3\n  selector:\n    matchLabels:\n      app: echo-app\n  template:\n    metadata:\n      labels:\n        app: echo-app\n    spec:\n      containers:\n      - name: echo-app\n        image: ghcr.io/philipschmid/echo-app:main\n        ports:\n        - name: http\n          containerPort: 8080\n        - name: tls\n          containerPort: 8443\n        - name: quic\n          containerPort: 4433\n          protocol: UDP\n        - name: tcp\n          containerPort: 9090\n        - name: grpc\n          containerPort: 50051\n        - name: metrics\n          containerPort: 3000\n        envFrom:\n        - configMapRef:\n            name: echo-app-config\n        env:\n        - name: ECHO_APP_NODE\n          valueFrom:\n            fieldRef:\n              fieldPath: spec.nodeName\n        livenessProbe:\n          httpGet:\n            path: /health\n            port: metrics\n          initialDelaySeconds: 5\n          periodSeconds: 10\n        readinessProbe:\n          httpGet:\n            path: /ready\n            port: metrics\n          initialDelaySeconds: 5\n          periodSeconds: 5\n        resources:\n          requests:\n            memory: \"64Mi\"\n            cpu: \"100m\"\n          limits:\n            memory: \"128Mi\"\n            cpu: \"500m\"\n---\napiVersion: v1\nkind: Service\nmetadata:\n  name: echo-app-service\nspec:\n  selector:\n    app: echo-app\n  ports:\n  - name: http\n    port: 8080\n    targetPort: 8080\n  - name: tls\n    port: 8443\n    targetPort: 8443\n  - name: quic\n    port: 4433\n    targetPort: 4433\n    protocol: UDP\n  - name: tcp\n    port: 9090\n    targetPort: 9090\n  - name: grpc\n    port: 50051\n    targetPort: 50051\n  - name: metrics\n    port: 3000\n    targetPort: 3000\n  type: ClusterIP\n```\n\n## License\n\nThis project is licensed under the Apache License 2.0 - see the LICENSE file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphilipschmid%2Fecho-app","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphilipschmid%2Fecho-app","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphilipschmid%2Fecho-app/lists"}