mirror of
https://github.com/MedUnes/go-kata.git
synced 2026-03-12 21:55:53 +07:00
49 lines
1.9 KiB
Markdown
49 lines
1.9 KiB
Markdown
# Kata 16: The HTTP Client Hygiene Wrapper
|
||
**Target Idioms:** `net/http` Transport Reuse, Timeouts, Context-First APIs, Response Body Draining
|
||
**Difficulty:** 🔴 Advanced
|
||
|
||
## 🧠 The "Why"
|
||
“Works locally” HTTP code in Go often fails in prod because people:
|
||
- use `http.DefaultClient` with no timeouts,
|
||
- create a new client/transport per request (connection churn),
|
||
- forget to close bodies (leaks + no keep-alive reuse),
|
||
- don’t drain bodies (prevents connection reuse).
|
||
|
||
This kata is about building a small internal SDK the **Go way**.
|
||
|
||
## 🎯 The Scenario
|
||
Your service calls a downstream API that sometimes returns large error bodies and sometimes hangs.
|
||
You need:
|
||
- strict timeouts,
|
||
- proper cancellation,
|
||
- safe connection reuse,
|
||
- structured logs.
|
||
|
||
## 🛠 The Challenge
|
||
Implement:
|
||
- `type APIClient struct { ... }`
|
||
- `func (c *APIClient) GetJSON(ctx context.Context, url string, out any) error`
|
||
|
||
### 1. Functional Requirements
|
||
- [ ] Use `http.NewRequestWithContext`.
|
||
- [ ] Decode JSON on 2xx responses into `out`.
|
||
- [ ] On non-2xx: read up to N bytes of body and return an error including status code.
|
||
|
||
### 2. The "Idiomatic" Constraints (Pass/Fail Criteria)
|
||
- [ ] **Must NOT** use `http.DefaultClient`.
|
||
- [ ] **Must** configure timeouts (`Client.Timeout` and/or transport-level timeouts).
|
||
- [ ] **Must** reuse a single `Transport` (connection pooling).
|
||
- [ ] **Must** `defer resp.Body.Close()`.
|
||
- [ ] **Must** drain (at least partially) error bodies to allow connection reuse.
|
||
- [ ] Use `slog` with fields: method, url, status, latency.
|
||
|
||
## 🧪 Self-Correction (Test Yourself)
|
||
- **If connections spike under load:** you probably rebuild transports.
|
||
- **If keep-alives don’t work:** you likely didn’t drain/close body.
|
||
- **If hangs occur:** you likely lack correct timeout configuration.
|
||
|
||
## 📚 Resources
|
||
- https://go.dev/src/net/http/client.go
|
||
- https://go.dev/src/net/http/transport.go
|
||
- https://blog.cloudflare.com/the-complete-guide-to-golang-net-http-timeouts/
|