@@ -9,21 +9,6 @@ import (
99 "net/http"
1010)
1111
12- // HTTPStatusCoder is interface that errors can implement to produce status code for HTTP response
13- type HTTPStatusCoder interface {
14- StatusCode () int
15- }
16-
17- // StatusCode returns status code from error if it implements HTTPStatusCoder interface.
18- // If error does not implement the interface it returns 0.
19- func StatusCode (err error ) int {
20- var sc HTTPStatusCoder
21- if errors .As (err , & sc ) {
22- return sc .StatusCode ()
23- }
24- return 0
25- }
26-
2712// Following errors can produce HTTP status code by implementing HTTPStatusCoder interface
2813var (
2914 ErrBadRequest = & httpError {http .StatusBadRequest } // 400
5035 ErrInvalidListenerNetwork = errors .New ("invalid listener network" )
5136)
5237
38+ // HTTPStatusCoder is interface that errors can implement to produce status code for HTTP response
39+ type HTTPStatusCoder interface {
40+ StatusCode () int
41+ }
42+
43+ // StatusCode returns status code from error if it implements HTTPStatusCoder interface.
44+ // If error does not implement the interface it returns 0.
45+ func StatusCode (err error ) int {
46+ var sc HTTPStatusCoder
47+ if errors .As (err , & sc ) {
48+ return sc .StatusCode ()
49+ }
50+ return 0
51+ }
52+
53+ // ResolveResponseStatus returns the Response and HTTP status code that should be (or has been) sent for rw,
54+ // given an optional error.
55+ //
56+ // This function is useful for middleware and handlers that need to figure out the HTTP status
57+ // code to return based on the error that occurred or what was set in the response.
58+ //
59+ // Precedence rules:
60+ // 1. If the response has already been committed, the committed status wins (err is ignored).
61+ // 2. Otherwise, start with 200 OK (net/http default if WriteHeader is never called).
62+ // 3. If the response has a non-zero suggested status, use it.
63+ // 4. If err != nil, it overrides the suggested status:
64+ // - StatusCode(err) if non-zero
65+ // - otherwise 500 Internal Server Error.
66+ func ResolveResponseStatus (rw http.ResponseWriter , err error ) (resp * Response , status int ) {
67+ resp , _ = UnwrapResponse (rw )
68+
69+ // once committed (sent to the client), the wire status is fixed; err cannot change it.
70+ if resp != nil && resp .Committed {
71+ if resp .Status == 0 {
72+ // unlikely path, but fall back to net/http implicit default if handler never calls WriteHeader
73+ return resp , http .StatusOK
74+ }
75+ return resp , resp .Status
76+ }
77+
78+ // net/http implicit default if handler never calls WriteHeader.
79+ status = http .StatusOK
80+
81+ // suggested status written from middleware/handlers, if present.
82+ if resp != nil && resp .Status != 0 {
83+ status = resp .Status
84+ }
85+
86+ // error overrides suggested status (matches typical Echo error-handler semantics).
87+ if err != nil {
88+ if s := StatusCode (err ); s != 0 {
89+ status = s
90+ } else {
91+ status = http .StatusInternalServerError
92+ }
93+ }
94+
95+ return resp , status
96+ }
97+
5398// NewHTTPError creates new instance of HTTPError
5499func NewHTTPError (code int , message string ) * HTTPError {
55100 return & HTTPError {
0 commit comments