Skip to content

Commit f248251

Browse files
author
wlanboy
committed
Updated readme
1 parent b752eb4 commit f248251

1 file changed

Lines changed: 247 additions & 45 deletions

File tree

README.md

Lines changed: 247 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,105 +2,307 @@
22

33
# JavaHttpClient
44

5-
Spring based rest service to test http routes in kubernetes.
6-
Showing http status, response, timing and istio envy settings.
5+
A Spring Boot REST service for testing and diagnosing HTTP routes in Kubernetes clusters with Istio service mesh. It acts as a configurable HTTP proxy that forwards requests to any target URL and returns the response along with timing, status and header information. Additionally it exposes Kubernetes and Istio diagnostic endpoints to inspect the service mesh configuration from within the cluster.
76

8-
## Web ui
7+
## Features
8+
9+
- **HTTP proxy** — forward GET, POST, PUT, DELETE, PATCH, HEAD and OPTIONS requests to any URL, with optional header forwarding and custom headers
10+
- **Kubernetes context** — read namespace, pod name and Istio sidecar status directly from the Kubernetes API
11+
- **Istio diagnostics** — list VirtualServices, DestinationRules, Gateways, ServiceEntries, Sidecars, EnvoyFilters, PeerAuthentications, RequestAuthentications and AuthorizationPolicies
12+
- **Istio full report** — fetch all Envoy configurations and error statistics of the Istio sidecar
13+
- **URL correlation** — check whether a given URL is covered by a VirtualService and which routes/DestinationRules apply
14+
- **TLS inspection** — open a direct TLS connection to a target and return protocol, cipher suite, certificate chain and SPIFFE/mTLS information
15+
- **Web UI** — browser-based frontend to interact with all endpoints
16+
- **OpenAPI/Swagger** — fully documented REST API with SpringDoc
17+
18+
## Tech Stack
19+
20+
| Component | Version |
21+
| --- | --- |
22+
| Java | 25 |
23+
| Spring Boot | 4.0.6 |
24+
| Servlet Container | Jetty (Tomcat excluded) |
25+
| OpenAPI | SpringDoc 3.0.3 |
26+
| Kubernetes Client | client-java 26.0.0 |
27+
| Observability | Micrometer Tracing + Actuator |
28+
29+
## Screenshots
30+
31+
### Web UI
932

1033
![web ui](./screenshots/httpclient-webui.png)
1134

12-
## Istio tab
35+
### Istio Tab
1336

1437
![istio tab](./screenshots/httpclient-istiotab.png)
1538

16-
## Swagger
39+
### Swagger UI
40+
41+
![swagger](./screenshots/httpclient-swagger.png)
42+
43+
### Helm Chart
1744

18-
![istio tab](./screenshots/httpclient-swagger.png)
45+
![helm chart](./screenshots/httpclient-helmchart.png)
1946

20-
# Build
47+
---
48+
49+
## Build
2150

2251
```bash
2352
mvn package
2453
```
2554

26-
# Docker build
55+
### Generate OpenAPI spec (`openapi.json`)
56+
57+
`mvn verify` starts the application as part of the integration test phase, calls `/api-docs`, writes the result to `target/openapi.json` and stops the application again. The file at the project root is the committed result of the last run.
2758

2859
```bash
29-
docker build -t wlanboy/javahttpclient:latest .
60+
mvn verify
61+
cp target/openapi.json openapi.json
3062
```
3163

32-
# Docker build with jlink and without
64+
---
65+
66+
## Docker
67+
68+
### Standard image (UBI9 + OpenJDK 25 JRE)
69+
70+
Uses the Red Hat UBI9 base image with the full OpenJDK 25 JRE. Includes Spring Boot AOT processing and CDS (Class Data Sharing) archive for faster startup.
3371

3472
```bash
3573
docker build -f Dockerfile25 -t javahttpclient:jre .
74+
```
75+
76+
### Minimal image (jlink custom JRE + distroless)
77+
78+
Uses `jlink` to create a custom JRE containing only the required modules, then packages it into a `gcr.io/distroless/cc` image. Includes AOT processing and a CDS archive built with the custom JRE.
79+
80+
```bash
3681
docker build -f Dockerfile25Jlink -t javahttpclient:jlink .
82+
```
3783

38-
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}" | grep "javahttpclient"
84+
### Image size comparison
85+
86+
```text
3987
javahttpclient jre 510MB
4088
javahttpclient jlink 295MB
4189
```
4290

43-
# Run container
91+
### Run
4492

4593
```bash
4694
docker run --rm --name httpclient --publish 8080:8080 javahttpclient:jre
4795

4896
docker run --rm --name httpclient --publish 8080:8080 javahttpclient:jlink
4997
```
5098

51-
# Docker hub
99+
### Multi-arch build
100+
101+
```bash
102+
bash multiarch-build.sh
103+
```
104+
105+
### Docker Hub
106+
107+
- <https://hub.docker.com/r/wlanboy/javahttpclient>
108+
109+
```bash
110+
docker build -t wlanboy/javahttpclient:latest .
111+
```
112+
113+
---
114+
115+
## API Reference
116+
117+
The full OpenAPI 3.1 specification is available in [openapi.json](./openapi.json).
118+
119+
Interactive Swagger UI: <http://localhost:8080/swagger-ui/index.html>
120+
121+
### `POST /client` — Forward an HTTP request
122+
123+
Forwards an HTTP request with the specified method, URL and optional body to the target system and returns the response.
124+
125+
**Request body** (`application/json`):
126+
127+
| Field | Type | Required | Description |
128+
| --- | --- | --- | --- |
129+
| `url` | string | yes | Target URL — must start with `http://` or `https://` |
130+
| `method` | string | yes | HTTP method: `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`, `OPTIONS` |
131+
| `body` | string | no | Optional request body |
132+
| `contentType` | string | no | Content-Type of the body, e.g. `application/json` |
133+
| `copyHeaders` | boolean | no | Copy incoming request headers to the forwarded request |
134+
| `customHeaders` | object | no | Additional headers to add, as `{"Header-Name": "value"}` |
135+
136+
**Responses:** `200` response from target, `400` validation error, `502` connection error.
137+
138+
#### Examples
139+
140+
Simple GET request:
141+
142+
```bash
143+
curl -X POST http://localhost:8080/client \
144+
-H 'Content-Type: application/json' \
145+
-d '{"url": "https://github.com", "method": "GET", "copyHeaders": false}'
146+
```
147+
148+
POST with body and custom content type:
149+
150+
```bash
151+
curl -X POST http://localhost:8080/client \
152+
-H 'Content-Type: application/json' \
153+
-d '{
154+
"url": "https://httpbin.org/post",
155+
"method": "POST",
156+
"body": "{\"hello\": \"world\"}",
157+
"contentType": "application/json",
158+
"copyHeaders": false
159+
}'
160+
```
161+
162+
Forward incoming headers and add a custom header:
163+
164+
```bash
165+
curl -X POST http://localhost:8080/client \
166+
-H 'Content-Type: application/json' \
167+
-H 'X-Correlation-Id: abc-123' \
168+
-d '{
169+
"url": "http://my-service.default.svc.cluster.local/api/v1/data",
170+
"method": "GET",
171+
"copyHeaders": true,
172+
"customHeaders": {"Authorization": "Bearer mytoken"}
173+
}'
174+
```
175+
176+
DNS resolution via a MirrorService:
177+
178+
```bash
179+
curl -X POST http://localhost:8080/client \
180+
-H 'Content-Type: application/json' \
181+
-d '{
182+
"url": "http://gmk:8003/resolve/google.com",
183+
"method": "GET",
184+
"copyHeaders": false
185+
}'
186+
```
187+
188+
---
189+
190+
### `GET /api/k8s/context` — Kubernetes context
191+
192+
Returns the current namespace, pod name and Istio sidecar status. Used by the web UI navbar on page load.
193+
194+
```bash
195+
curl http://localhost:8080/api/k8s/context
196+
```
197+
198+
---
199+
200+
### `GET /api/k8s/status` — Kubernetes client status
201+
202+
Shows whether the Kubernetes API client was initialized successfully and lists supported Istio resource types and API versions.
203+
204+
```bash
205+
curl http://localhost:8080/api/k8s/status
206+
```
207+
208+
---
209+
210+
### `GET /api/k8s/istio/{type}` — List Istio resources
211+
212+
Lists specific Istio resources in a namespace. The `namespace` query parameter defaults to `default`.
213+
214+
Supported types: `virtualservices`, `destinationrules`, `gateways`, `serviceentries`, `sidecars`, `envoyfilters`, `peerauthentications`, `requestauthentications`, `authorizationpolicies`
215+
216+
```bash
217+
# List all VirtualServices in the default namespace
218+
curl "http://localhost:8080/api/k8s/istio/virtualservices"
219+
220+
# List DestinationRules in a specific namespace
221+
curl "http://localhost:8080/api/k8s/istio/destinationrules?namespace=production"
222+
223+
# List PeerAuthentications (mTLS policies)
224+
curl "http://localhost:8080/api/k8s/istio/peerauthentications?namespace=istio-system"
225+
```
226+
227+
---
228+
229+
### `GET /api/k8s/istio/full-report` — Istio full report
230+
231+
Fetches all Envoy configurations and error statistics of the Istio sidecar. Returns `200` even on error — the body contains the error description in that case.
232+
233+
```bash
234+
curl http://localhost:8080/api/k8s/istio/full-report
235+
```
236+
237+
---
52238

53-
* https://hub.docker.com/r/wlanboy/javahttpclient
239+
### `GET /api/k8s/correlate` — Correlate URL with Istio routing
54240

55-
# Test java http client
241+
Checks whether the given URL is covered by a VirtualService and which routes and DestinationRules apply.
56242

57243
```bash
58-
curl -L -X POST 'http://127.0.0.1:8080/client' -H 'Content-Type: application/json' \
59-
-d '{"url" : "https://github.com", "copyHeaders": "false"}'
244+
curl "http://localhost:8080/api/k8s/correlate?url=http://my-service.default.svc.cluster.local/api/v1&namespace=default"
60245
```
61246

62-
# local dev
247+
---
248+
249+
### `GET /api/k8s/tls` — Inspect TLS certificate
250+
251+
Opens a direct TLS connection to the target URL and returns protocol, cipher suite, the full certificate chain and SPIFFE/mTLS information. The URL must use `https://`.
63252

64253
```bash
254+
curl "http://localhost:8080/api/k8s/tls?url=https://example.com"
255+
256+
# Inspect mTLS within the mesh
257+
curl "http://localhost:8080/api/k8s/tls?url=https://my-service.default.svc.cluster.local"
258+
```
259+
260+
---
261+
262+
## Local development with mirrord
263+
264+
[mirrord](https://mirrord.dev) lets you run the application locally while it intercepts traffic from a pod running in the cluster — useful for debugging without a full cluster deployment.
265+
266+
```bash
267+
# Install mirrord
65268
curl -fsSL https://raw.githubusercontent.com/metalbear-co/mirrord/main/scripts/install.sh | bash
66269

270+
# Look up the target pod
67271
POD=$(kubectl get pod -n javahttpclient -l app=javahttpclient -o jsonpath='{.items[0].metadata.name}')
68272

69-
mirrord exec -n javahttpclient --target deployment/javahttpclient -- mvn spring-boot:run
273+
# Run with Maven (hot reload)
274+
mirrord exec -n javahttpclient --target deployment/javahttpclient -- mvn spring-boot:run
70275

276+
# Run the packaged JAR against a specific pod
71277
mirrord exec -n javahttpclient --target pod/$POD -- java -jar target/javahttpclient-0.0.1-SNAPSHOT.jar
72278

279+
# Run the packaged JAR against the deployment
73280
mirrord exec -n javahttpclient --target deployment/javahttpclient -- java -jar target/javahttpclient-0.0.1-SNAPSHOT.jar
74281
```
75282

76-
# swagger uri
283+
---
77284

78-
* http://localhost:8080/swagger-ui/index.html#/http-client-controller/postMapping
285+
## Kubernetes / Helm deployment
79286

80-
# curl calls for mirrorservice
81-
82-
* see: https://github.com/wlanboy/MirrorService
287+
The chart is located in [javahttpclient-chart/](./javahttpclient-chart/). It includes Deployment, Service, ServiceAccount, RBAC, ConfigMap, Certificate, Gateway and VirtualService templates.
83288

84289
```bash
85-
curl -X 'POST' \
86-
'http://localhost:8080/client' \
87-
-H 'accept: */*' \
88-
-H 'Content-Type: application/json' \
89-
-d '{
90-
"url": "http://gmk:8003/resolve/google.com",
91-
"method": "GET",
92-
"body": "",
93-
"copyHeaders": false
94-
}'
95-
96-
curl -X 'POST' \
97-
'http://localhost:8080/client' \
98-
-H 'accept: */*' \
99-
-H 'Content-Type: application/json' \
100-
-d '{
101-
"url": "http://gmk:8003/mirror?request=HalloWelt&statuscode=200&wait=4",
102-
"method": "GET",
103-
"body": "",
104-
"copyHeaders": true
105-
}'
290+
# Install
291+
helm install httpclient ./javahttpclient-chart -n clients --create-namespace
292+
293+
# Verify
294+
kubectl get gateway,virtualservice -n clients
295+
kubectl get secret httpclient-tls -n istio-ingress
296+
297+
# Upgrade
298+
helm upgrade httpclient ./javahttpclient-chart -n clients
299+
300+
# Uninstall
301+
helm uninstall httpclient -n clients
106302
```
303+
304+
---
305+
306+
## Related projects
307+
308+
- [MirrorService](https://github.com/wlanboy/MirrorService) — echo/mirror service for testing HTTP routing and response simulation

0 commit comments

Comments
 (0)