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  }