Skip to content

Commit ee6e449

Browse files
authored
docs: update readme (#4)
* docs: cleanup * docs: cleanup * docs: cleanup * docs: cleanup * docs: cleanup * docs: cleanup * docs: cleanup * docs: cleanup * docs: tweaks
1 parent a12d015 commit ee6e449

6 files changed

Lines changed: 80 additions & 79 deletions

File tree

README.md

Lines changed: 70 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,10 @@ It keeps req's power and escape hatches, while making the 90% use case feel effo
2222
<img src="docs/images/goforj_httpx_example_1.png" alt="httpx Logo">
2323
</p>
2424

25-
## v2 Status
26-
27-
httpx v1 has been tagged and is now frozen. The `main` branch is v2, which includes intentional breaking changes to improve API clarity and ergonomics (for example, request helpers return `(T, error)`).
28-
2925
## Why httpx
3026

27+
- Developer-first ergonomics: fast to read, fast to write, predictable to use.
28+
- Reliability by default: sensible timeouts, safe error handling, resilient retries.
3129
- Typed, zero-ceremony requests with generics.
3230
- Opinionated defaults (timeouts, result handling, safe error mapping).
3331
- Built on req, with full escape hatches via `Client.Req()` and `Client.Raw()`.
@@ -42,58 +40,71 @@ go get github.com/goforj/httpx
4240
## Quick Start
4341

4442
```go
45-
package main
46-
47-
import (
48-
"context"
49-
"fmt"
50-
"net/http"
43+
type User struct {
44+
ID int `json:"id"`
45+
Name string `json:"name"`
46+
}
5147

52-
"github.com/goforj/httpx"
53-
"github.com/imroc/req/v3"
48+
c := httpx.New(
49+
httpx.BaseURL("https://api.example.com"),
50+
httpx.Bearer("token"),
51+
// options...
5452
)
5553

56-
func main() {
57-
c := httpx.New()
58-
59-
// Simple typed GET.
60-
res, err := httpx.Get[map[string]any](c, "https://httpbin.org/get")
61-
if err != nil {
62-
panic(err)
63-
}
64-
fmt.Println(res)
65-
66-
// Context-aware GET.
67-
ctx := context.Background()
68-
res2, err := httpx.GetCtx[map[string]any](c, ctx, "https://httpbin.org/get")
69-
if err != nil {
70-
panic(err)
71-
}
72-
fmt.Println(res2)
73-
74-
// Access the underlying response when you need it.
75-
r := req.C().R()
76-
r.SetURL("https://httpbin.org/get")
77-
r.Method = http.MethodGet
78-
res3, resp, err := httpx.Do[map[string]any](r)
79-
if err != nil {
80-
panic(err)
81-
}
82-
fmt.Println(res3)
83-
fmt.Println(resp.Status)
84-
}
54+
// httpx.Get[T](client, url, options...)
55+
user, _ := httpx.Get[User](c, "/users/42", httpx.Query("include", "profile"))
56+
fmt.Println(user.Name)
8557
```
8658

87-
## v2 Error Handling
59+
All request helpers return `(T, error)`. The low-level escape hatch `Do` returns `(T, *req.Response, error)` when you need raw access.
60+
61+
## Core Surface (use these first)
8862

89-
httpx v2 returns errors as the second return value from request helpers.
63+
- Requests: `Get / Post / Put / Patch / Delete` (+ `*Ctx`)
64+
- Composition: `Query`, `Path`, `Header`, `JSON`
65+
- Client defaults: `New(...)` with BaseURL, auth, timeouts
66+
- Resiliency: `Retry*`
67+
- Debug: `Dump`
68+
- Power-user: `Req` / `Raw` escape hatch
69+
70+
## Most Common Tasks
71+
72+
Brevity-first, idiomatic patterns. Handle errors; dump what matters.
73+
74+
Singular helpers (`Query`, `Path`, `Header`) set one value; plural helpers (`Queries`, `Paths`, `Headers`) set many at once.
9075

9176
```go
92-
res, err := httpx.Get[map[string]any](c, "https://httpbin.org/get")
93-
if err != nil {
94-
return err
77+
type GetResponse struct {
78+
URL string `json:"url"`
79+
}
80+
type CreateUser struct {
81+
Name string `json:"name"`
82+
}
83+
type CreateUserResponse struct {
84+
JSON CreateUser `json:"json"`
9585
}
96-
_ = res
86+
87+
c := httpx.New()
88+
89+
// Simple request
90+
res, _ := httpx.Get[GetResponse](c, "https://httpbin.org/get")
91+
httpx.Dump(res) // URL => "https://httpbin.org/get"
92+
93+
// POST JSON with typed request/response
94+
resPost, _ := httpx.Post[CreateUser, CreateUserResponse](c, "https://httpbin.org/post", CreateUser{Name: "Ana"})
95+
httpx.Dump(resPost) // JSON.Name => "Ana"
96+
97+
// Passing a header option
98+
res, _ = httpx.Get[map[string]any](c, "https://httpbin.org/headers", httpx.Header("X-Test", "true"))
99+
httpx.Dump(res) // headers.X-Test => "true"
100+
101+
// Passing query params
102+
res, _ = httpx.Get[map[string]any](c, "https://httpbin.org/get", httpx.Query("q", "search"))
103+
httpx.Dump(res) // args.q => "search"
104+
105+
// File upload
106+
resUpload, _ := httpx.Post[any, map[string]any](c, "https://httpbin.org/post", nil, httpx.File("file", "./report.txt"))
107+
httpx.Dump(resUpload) // files.file => "...report.txt"
97108
```
98109

99110
## Browser Profiles
@@ -138,11 +149,12 @@ res, err := httpx.Get[map[string]any](
138149
httpx.Path("id", "42"),
139150
httpx.Query("include", "teams", "active", "1"),
140151
httpx.Header("Accept", "application/json"),
152+
// stack more options...
141153
)
142154
if err != nil {
143-
panic(err)
155+
// handle error
144156
}
145-
_ = res
157+
httpx.Dump(res) // dumps map[string]any
146158
```
147159

148160
## Debugging and Tracing
@@ -162,6 +174,10 @@ They are compiled by `example_compile_test.go` to keep docs and code in sync.
162174
- Run `go run ./docs/readme/main.go` to refresh the API index and test count.
163175
- Run `go test ./...`.
164176

177+
## v2 Status
178+
179+
httpx v1 has been tagged and is now frozen. The `main` branch is v2, which includes intentional breaking changes to improve API clarity and ergonomics (for example, request helpers return `(T, error)`).
180+
165181
<!-- api:embed:start -->
166182

167183
## API Index
@@ -722,7 +738,7 @@ httpx.Dump(res) // dumps map[string]any
722738

723739
### <a id="json"></a>JSON
724740

725-
JSON sets the request body as JSON.
741+
JSON forces JSON encoding for the request body (even when inference might choose differently).
726742

727743
```go
728744
type Payload struct {
@@ -890,6 +906,7 @@ httpx.Dump(res) // dumps DeleteResponse
890906
### <a id="do"></a>Do
891907

892908
Do executes a pre-configured req request and returns the decoded body and response.
909+
This is the low-level escape hatch when you need full req control.
893910

894911
```go
895912
r := req.C().R().SetHeader("X-Trace", "1")
@@ -921,10 +938,7 @@ type GetResponse struct {
921938
}
922939

923940
c := httpx.New()
924-
res, err := httpx.Get[GetResponse](c, "https://httpbin.org/get")
925-
if err != nil {
926-
return
927-
}
941+
res, _ := httpx.Get[GetResponse](c, "https://httpbin.org/get")
928942
httpx.Dump(res)
929943
// #GetResponse {
930944
// URL => "https://httpbin.org/get" #string
@@ -934,11 +948,8 @@ httpx.Dump(res)
934948
_Example: bind to a string body_
935949

936950
```go
937-
resText, err := httpx.Get[string](c, "https://httpbin.org/uuid")
938-
if err != nil {
939-
return
940-
}
941-
println(resText) // dumps string
951+
resString, _ := httpx.Get[string](c, "https://httpbin.org/uuid")
952+
println(resString) // dumps string
942953
// {
943954
// "uuid": "becbda6d-9950-4966-ae23-0369617ba065"
944955
// }

client.go

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -118,22 +118,16 @@ func (c *Client) clone() *Client {
118118
// }
119119
//
120120
// c := httpx.New()
121-
// res, err := httpx.Get[GetResponse](c, "https://httpbin.org/get")
122-
// if err != nil {
123-
// return
124-
// }
121+
// res, _ := httpx.Get[GetResponse](c, "https://httpbin.org/get")
125122
// httpx.Dump(res)
126123
// // #GetResponse {
127124
// // URL => "https://httpbin.org/get" #string
128125
// // }
129126
//
130127
// Example: bind to a string body
131128
//
132-
// resText, err := httpx.Get[string](c, "https://httpbin.org/uuid")
133-
// if err != nil {
134-
// return
135-
// }
136-
// println(resText) // dumps string
129+
// resString, _ := httpx.Get[string](c, "https://httpbin.org/uuid")
130+
// println(resString) // dumps string
137131
// // {
138132
// // "uuid": "becbda6d-9950-4966-ae23-0369617ba065"
139133
// // }
@@ -447,6 +441,7 @@ func OptionsCtx[T any](client *Client, ctx context.Context, url string, opts ...
447441
}
448442

449443
// Do executes a pre-configured req request and returns the decoded body and response.
444+
// This is the low-level escape hatch when you need full req control.
450445
// @group Requests
451446
//
452447
// Example: advanced request with response access

examples/do/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
func main() {
1313
// Do executes a pre-configured req request and returns the decoded body and response.
14+
// This is the low-level escape hatch when you need full req control.
1415

1516
// Example: advanced request with response access
1617
r := req.C().R().SetHeader("X-Trace", "1")

examples/get/main.go

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,15 @@ func main() {
1414
}
1515

1616
c := httpx.New()
17-
res, err := httpx.Get[GetResponse](c, "https://httpbin.org/get")
18-
if err != nil {
19-
return
20-
}
17+
res, _ := httpx.Get[GetResponse](c, "https://httpbin.org/get")
2118
httpx.Dump(res)
2219
// #GetResponse {
2320
// URL => "https://httpbin.org/get" #string
2421
// }
2522

2623
// Example: bind to a string body
27-
resText, err := httpx.Get[string](c, "https://httpbin.org/uuid")
28-
if err != nil {
29-
return
30-
}
31-
println(resText) // dumps string
24+
resString, _ := httpx.Get[string](c, "https://httpbin.org/uuid")
25+
println(resString) // dumps string
3226
// {
3327
// "uuid": "becbda6d-9950-4966-ae23-0369617ba065"
3428
// }

examples/json/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ package main
66
import "github.com/goforj/httpx"
77

88
func main() {
9-
// JSON sets the request body as JSON.
9+
// JSON forces JSON encoding for the request body (even when inference might choose differently).
1010

1111
// Example: force JSON body
1212
type Payload struct {

options_request.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ func (b OptionBuilder) Body(value any) OptionBuilder {
278278
}))
279279
}
280280

281-
// JSON sets the request body as JSON.
281+
// JSON forces JSON encoding for the request body (even when inference might choose differently).
282282
// @group Request Composition
283283
//
284284
// Applies to individual requests only.

0 commit comments

Comments
 (0)