https://github.com/kloudkit/looking-glass
🔎 Drop-in HTTP request reflector — see exactly what is hitting your service
https://github.com/kloudkit/looking-glass
container debugging-tool echo-server http-debugging
Last synced: 23 days ago
JSON representation
🔎 Drop-in HTTP request reflector — see exactly what is hitting your service
- Host: GitHub
- URL: https://github.com/kloudkit/looking-glass
- Owner: kloudkit
- License: mit
- Created: 2026-06-10T07:58:33.000Z (30 days ago)
- Default Branch: main
- Last Pushed: 2026-06-10T09:09:10.000Z (30 days ago)
- Last Synced: 2026-06-10T10:14:10.511Z (30 days ago)
- Topics: container, debugging-tool, echo-server, http-debugging
- Language: Go
- Homepage:
- Size: 23.4 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# Kloud • Looking Glass
> 🔎 **Drop-in HTTP request reflector** — see *exactly* what is hitting your service
[](https://github.com/kloudkit/looking-glass/stargazers)
[](https://github.com/kloudkit/looking-glass/pkgs/container/looking-glass)
[](https://github.com/kloudkit/looking-glass/actions/workflows/build.yaml)
[](https://github.com/kloudkit/looking-glass/blob/main/LICENSE)
---
```sh
# TL;DR 🔎 run the reflector on :8080
docker run --rm -p 8080:8080 ghcr.io/kloudkit/looking-glass:latest
```
Then point anything at it — every method, every path is answered with the full
request it received (method, URL, query, headers, client address, body).
The **HTTP response** is `html` by default and `json` on demand, selected by a
dedicated header so it never collides with the request's own `Accept` — or by a
`?format=` query param so the JSON view is reachable straight from a browser
address bar:
```sh
# HTML (default)
curl 'localhost:8080/api/users?page=2'
# JSON via header
curl -X POST 'localhost:8080/api/users?page=2' -d '{"name":"ada"}' -H 'X-Glass-Format: json'
```
```text
# JSON in a browser — just add ?format=json to the URL
http://localhost:8080/api/users?page=2&format=json
```
The HTML view also carries a **Copy as** control in the corner — grab the request
as pretty `JSON` or as a `Raw` HTTP dump (request line, headers, body) without
leaving the page.
Meanwhile the **container logs stay a concise, colored activity stream** — one
line per request (time, client, method, path, response format, body size), never
the request contents:
```sh
docker logs -f
# 2026/06/10 12:00:00 10.0.0.1:54321 POST /api/users?page=2 → html 14b
```
## What's Inside
- **Wildcard everything** — every HTTP method on every path returns `200` with
the full request reflected back.
- **Two response formats** — `html` (default) or `json`, chosen with the
`X-Glass-Format` header (never the request's `Accept`).
- **Copy as** — the HTML view copies the request to your clipboard as pretty
`JSON` or a `Raw` HTTP dump, no devtools required.
- **Colored activity log** — stdout gets one readable line per request (time,
client, method, path, format, size), so `docker logs` stays a clean access
stream and request contents never leak into the logs.
- **Safe HTML** — reflected values are escaped, so a malicious body can't execute
in the browser; the logged path is stripped of control characters.
- **Bounded** — request bodies are capped (default `1 MiB`) so a stray upload
can't take the box down; truncation is shown in every rendering.
- **Tiny image** — a single static Go binary on a shell-less, non-root distroless
base.
## Configuration
| Variable | Default | Description |
| ---------------- | --------- | ---------------------------------------- |
| `PORT` | `8080` | Port to listen on. |
| `MAX_BODY_BYTES` | `1048576` | Max body bytes reflected before cut-off. |
| Selector | Values | Effect |
| ----------------------- | --------------- | ------------------------------------------- |
| `X-Glass-Format` header | `html` / `json` | Response format. Takes precedence. |
| `?format=` query param | `html` / `json` | Browser-friendly fallback. Defaults `html`. |
## Getting Started
Run it straight from source while iterating locally:
```sh
go run .
# in another shell
curl -X DELETE 'localhost:8080/anything/here'
```
Or build the image yourself:
```sh
docker build -t looking-glass .
docker run --rm -p 8080:8080 looking-glass
```
> 💡 The final image is [distroless](https://github.com/GoogleContainerTools/distroless)
> and shell-less. Swap the final stage for `scratch` to shave it further, or for
> `ghcr.io/kloudkit/base-image` if you want a shell to exec into.
## License
Released under the [**MIT License**](https://github.com/kloudkit/looking-glass/blob/main/LICENSE)