github.com/qiniu/go-sdk/v7@v7.27.0/sandbox/errors.go (about) 1 package sandbox 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 8 "connectrpc.com/connect" 9 ) 10 11 // APIError 表示 API 返回的非预期 HTTP 响应。 12 type APIError struct { 13 StatusCode int 14 Body []byte 15 16 // Reqid 是从响应头 X-Reqid 中提取的请求 ID,用于链路追踪和日志排查。 17 Reqid string 18 // Code 是从响应 body 中解析出的错误码(如果有)。 19 Code string 20 // Message 是从响应 body 中解析出的错误消息(如果有)。 21 Message string 22 } 23 24 // Error 实现 error 接口。 25 func (e *APIError) Error() string { 26 prefix := fmt.Sprintf("api error: status %d", e.StatusCode) 27 if e.Reqid != "" { 28 prefix += ", reqid: " + e.Reqid 29 } 30 if e.Message != "" { 31 return prefix + ": " + e.Message 32 } 33 if len(e.Body) > 0 { 34 return prefix + ", body: " + string(e.Body) 35 } 36 return prefix 37 } 38 39 // newAPIError 从 HTTP 响应创建 APIError,提取 X-Reqid 头并解析 JSON body。 40 func newAPIError(resp *http.Response, body []byte) *APIError { 41 e := &APIError{ 42 StatusCode: resp.StatusCode, 43 Body: body, 44 Reqid: resp.Header.Get("X-Reqid"), 45 } 46 e.Code, e.Message = parseAPIErrorBody(body) 47 return e 48 } 49 50 // parseAPIErrorBody 尝试从 JSON body 中解析 code 和 message 字段。 51 func parseAPIErrorBody(body []byte) (code, message string) { 52 if len(body) == 0 { 53 return "", "" 54 } 55 var parsed struct { 56 Code string `json:"code"` 57 Message string `json:"message"` 58 } 59 if json.Unmarshal(body, &parsed) == nil { 60 return parsed.Code, parsed.Message 61 } 62 return "", "" 63 } 64 65 // isNotFoundError 判断错误是否为"未找到"类型。 66 func isNotFoundError(err error) bool { 67 if apiErr, ok := err.(*APIError); ok { 68 return apiErr.StatusCode == http.StatusNotFound 69 } 70 if connect.CodeOf(err) == connect.CodeNotFound { 71 return true 72 } 73 return false 74 }