0 Star 0 Fork 0

蒋佳李/vault

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
response_util.go 4.55 KB
一键复制 编辑 原始数据 按行查看 历史
蒋佳李 提交于 2021-03-25 16:28 . 更新
package logical
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"gitee.com/jiangjiali/vault/sdk/helper/consts"
"gitee.com/jiangjiali/vault/sdk/helper/errwrap"
"gitee.com/jiangjiali/vault/sdk/helper/multierror"
)
// RespondErrorCommon pulls most of the functionality from http's
// respondErrorCommon and some of http's handleLogical and makes it available
// to both the http package and elsewhere.
func RespondErrorCommon(req *Request, resp *Response, err error) (int, error) {
if err == nil && (resp == nil || !resp.IsError()) {
switch {
case req.Operation == ReadOperation:
if resp == nil {
return http.StatusNotFound, nil
}
// Basically: if we have empty "keys" or no keys at all, 404. This
// provides consistency with GET.
case req.Operation == ListOperation && (resp == nil || resp.WrapInfo == nil):
if resp == nil {
return http.StatusNotFound, nil
}
if len(resp.Data) == 0 {
if len(resp.Warnings) > 0 {
return 0, nil
}
return http.StatusNotFound, nil
}
keysRaw, ok := resp.Data["keys"]
if !ok || keysRaw == nil {
// If we don't have keys but have other data, return as-is
if len(resp.Data) > 0 || len(resp.Warnings) > 0 {
return 0, nil
}
return http.StatusNotFound, nil
}
var keys []string
switch keysRaw.(type) {
case []interface{}:
keys = make([]string, len(keysRaw.([]interface{})))
for i, el := range keysRaw.([]interface{}) {
s, ok := el.(string)
if !ok {
return http.StatusInternalServerError, nil
}
keys[i] = s
}
case []string:
keys = keysRaw.([]string)
default:
return http.StatusInternalServerError, nil
}
if len(keys) == 0 {
return http.StatusNotFound, nil
}
}
return 0, nil
}
if errwrap.ContainsType(err, new(ReplicationCodedError)) {
var allErrors error
var codedErr *ReplicationCodedError
errwrap.Walk(err, func(inErr error) {
newErr, ok := inErr.(*ReplicationCodedError)
if ok {
codedErr = newErr
} else {
allErrors = multierror.Append(allErrors, inErr)
}
})
if allErrors != nil {
return codedErr.Code, multierror.Append(errors.New(fmt.Sprintf("errors from both primary and secondary; primary error was %v; secondary errors follow", codedErr.Msg)), allErrors)
}
return codedErr.Code, errors.New(codedErr.Msg)
}
// Start out with internal server error since in most of these cases there
// won't be a response so this won't be overridden
statusCode := http.StatusInternalServerError
// If we actually have a response, start out with bad request
if resp != nil {
statusCode = http.StatusBadRequest
}
// Now, check the error itself; if it has a specific logical error, set the
// appropriate code
if err != nil {
switch {
case errwrap.ContainsType(err, new(StatusBadRequest)):
statusCode = http.StatusBadRequest
case errwrap.Contains(err, ErrPermissionDenied.Error()):
statusCode = http.StatusForbidden
case errwrap.Contains(err, ErrUnsupportedOperation.Error()):
statusCode = http.StatusMethodNotAllowed
case errwrap.Contains(err, ErrUnsupportedPath.Error()):
statusCode = http.StatusNotFound
case errwrap.Contains(err, ErrInvalidRequest.Error()):
statusCode = http.StatusBadRequest
case errwrap.Contains(err, ErrUpstreamRateLimited.Error()):
statusCode = http.StatusBadGateway
}
}
if resp != nil && resp.IsError() {
err = fmt.Errorf("%s", resp.Data["error"].(string))
}
return statusCode, err
}
// AdjustErrorStatusCode adjusts the status that will be sent in error
// conditions in a way that can be shared across http's respondError and other
// locations.
func AdjustErrorStatusCode(status *int, err error) {
// Handle nested errors
if t, ok := err.(*multierror.Error); ok {
for _, e := range t.Errors {
AdjustErrorStatusCode(status, e)
}
}
// Adjust status code when sealed
if errwrap.Contains(err, consts.ErrSealed.Error()) {
*status = http.StatusServiceUnavailable
}
// Adjust status code on
if errwrap.Contains(err, "http: request body too large") {
*status = http.StatusRequestEntityTooLarge
}
// Allow HTTPCoded error passthrough to specify a code
if t, ok := err.(HTTPCodedError); ok {
*status = t.Code()
}
}
func RespondError(w http.ResponseWriter, status int, err error) {
AdjustErrorStatusCode(&status, err)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
type ErrorResponse struct {
Errors []string `json:"errors"`
}
resp := &ErrorResponse{Errors: make([]string, 0, 1)}
if err != nil {
resp.Errors = append(resp.Errors, err.Error())
}
enc := json.NewEncoder(w)
enc.Encode(resp)
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/jiangjiali/vault.git
git@gitee.com:jiangjiali/vault.git
jiangjiali
vault
vault
v1.1.8

搜索帮助