maragudk / maragudk/gomponents

Use errors.As in http.Adapt to find StatusCode in wrapped errors

Open Beginner friendly
#353 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Go
Stars
1.9k
Forks
59
Avg merge
1d 12h
Merged PRs (30d)
17

Description

`http.Adapt` looks for a `StatusCode() int` method with a type switch on the returned error:

```go
switch v := err.(type) {
case errorWithStatusCode:
w.WriteHeader(v.StatusCode())
default:
w.WriteHeader(http.StatusInternalServerError)
}
```

That only matches when the returned error itself has the method. Wrapping an error for context is idiomatic Go, but the wrapper doesn't have `StatusCode()`, so the status in the chain is ignored and the response is a 500:

```go
type notFoundError struct{}

func (notFoundError) Error() string { return "not found" }
func (notFoundError) StatusCode() int { return http.StatusNotFound }

// Responds 404.
return html.NotFoundPage(), notFoundError{}

// Responds 500.
return html.NotFoundPage(), fmt.Errorf("get user %v: %w", id, notFoundError{})
```

Verified on main (833b404) with `httptest`.

Proposal: find the status with `errors.As`, so any error in the chain that has `StatusCode()` sets the response status. Errors that match today still match, because `errors.As` checks the error itself first. The only change is for wrapped errors, which currently get a 500. `errors.As` has been in the standard library since Go 1.13, so the Go 1.18 minimum is unaffected.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at http.Adapt and inspect its existing error-to-status handling and related tests. Use httptest to compare an unwrapped StatusCode error with the same error wrapped using %w. Done means wrapped errors in the chain produce their StatusCode while existing direct-error behavior remains unchanged.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
api, backend
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.