Skip to content

Commit

Permalink
Add ResponseEmpty to skip HTTP body
Browse files Browse the repository at this point in the history
  • Loading branch information
glossd committed Nov 11, 2024
1 parent 5058021 commit c5d5b93
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 4 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,15 @@ if resp.Status == 200 {
fmt.Println("Response headers", resp.Headers())
}
```
If you don't need the HTTP body you can use `fetch.ResponseEmpty`
```go
res, err := fetch.Delete[fetch.ResponseEmpty]("https://petstore.swagger.io/v2/pet/10")
if err != nil {
panic(err)
}
fmt.Println("Status:", res.Status)
fmt.Println("Headers:", res.Headers())
```
#### Error handling
The error will contain the status and other http attributes
```go
Expand Down
14 changes: 10 additions & 4 deletions fetch.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,19 +161,25 @@ func Request[T any](url string, config ...Config) (T, *Error) {
}
}()

var t T
typeOf := reflect.TypeOf(t)

if typeOf != nil && typeOf == typeFor[ResponseEmpty]() {
re := any(&t).(*ResponseEmpty)
re.Status = res.StatusCode
re.DuplicateHeaders = res.Header
return t, nil
}

body, err := io.ReadAll(res.Body)
if err != nil {
var t T
return t, httpErr("read http body: ", err, res)
}

if firstDigit(res.StatusCode) != 2 {
var t T
return t, httpErr(fmt.Sprintf("http status=%d, body=", res.StatusCode), errors.New(string(body)), res)
}

var t T
typeOf := reflect.TypeOf(t)
if typeOf != nil && typeOf.PkgPath() == "github.com/glossd/fetch" && strings.HasPrefix(typeOf.Name(), "Response[") {
resType, ok := typeOf.FieldByName("Body")
if !ok {
Expand Down
13 changes: 13 additions & 0 deletions fetch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,19 @@ func TestRequest_ResponseT(t *testing.T) {
}
}

func TestRequest_ResponseEmpty(t *testing.T) {
res, err := Request[ResponseEmpty]("key.value")
if err != nil {
t.Error(err)
}
if res.Status != 200 {
t.Errorf("response status isn't 200")
}
if res.Headers()["Content-type"] != "application/json" {
t.Errorf("wrong headers")
}
}

func TestPostString(t *testing.T) {
j, err := Post[M]("echo.me", `{"hello":"whosthere"}`)
if err != nil {
Expand Down
27 changes: 27 additions & 0 deletions response.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
package fetch

/*
Response is a wrapper type for (generic) ReturnType to be used in
the HTTP methods. It allows you to access HTTP attributes
of the HTTP response and unmarshal the HTTP body.
e.g.
type User struct {
FirstName string
}
res, err := Get[Response[User]]("/users/1")
if err != nil {panic(err)}
if res.Status != 202 {
panic("unexpected status")
}
// Body is User type
fmt.Println(res.Body.FirstName)
*/
type Response[T any] struct {
Status int
DuplicateHeaders map[string][]string
Expand All @@ -11,6 +27,17 @@ func (r Response[T]) Headers() map[string]string {
return uniqueHeaders(r.DuplicateHeaders)
}

// ResponseEmpty is a special ResponseType that completely ignores the HTTP body.
// Can be used as the (generic) ReturnType for any HTTP method.
type ResponseEmpty struct {
Status int
DuplicateHeaders map[string][]string
}

func (r ResponseEmpty) Headers() map[string]string {
return uniqueHeaders(r.DuplicateHeaders)
}

func uniqueHeaders(headers map[string][]string) map[string]string {
h := make(map[string]string, len(headers))
for key, val := range headers {
Expand Down

0 comments on commit c5d5b93

Please sign in to comment.