2023-08-31 11:37:03 +03:00
|
|
|
package handler
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2025-01-09 12:28:38 +03:00
|
|
|
"errors"
|
|
|
|
"fmt"
|
2023-08-31 11:37:03 +03:00
|
|
|
"strings"
|
|
|
|
|
2025-03-03 18:06:41 +03:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/layer"
|
2023-08-31 11:37:03 +03:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/logs"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/tokens"
|
2025-03-03 18:06:41 +03:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/utils"
|
2023-08-31 11:37:03 +03:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
2024-09-18 07:35:26 +03:00
|
|
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
2024-10-10 11:59:53 +03:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
2024-09-18 07:35:26 +03:00
|
|
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
2023-08-31 11:37:03 +03:00
|
|
|
"github.com/valyala/fasthttp"
|
|
|
|
"go.uber.org/zap"
|
|
|
|
)
|
|
|
|
|
|
|
|
func bearerToken(ctx context.Context) *bearer.Token {
|
|
|
|
if tkn, err := tokens.LoadBearerToken(ctx); err == nil {
|
|
|
|
return tkn
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-09-26 17:32:27 +03:00
|
|
|
func isDir(name string) bool {
|
2024-12-02 11:45:30 +03:00
|
|
|
return name == "" || strings.HasSuffix(name, "/")
|
2024-09-26 17:32:27 +03:00
|
|
|
}
|
|
|
|
|
2024-10-10 11:59:53 +03:00
|
|
|
func loadAttributes(attrs []object.Attribute) map[string]string {
|
|
|
|
result := make(map[string]string)
|
|
|
|
for _, attr := range attrs {
|
|
|
|
result[attr.Key()] = attr.Value()
|
2024-09-26 17:32:27 +03:00
|
|
|
}
|
2024-10-10 11:59:53 +03:00
|
|
|
return result
|
2024-09-26 17:32:27 +03:00
|
|
|
}
|
|
|
|
|
2023-08-31 11:37:03 +03:00
|
|
|
func isValidToken(s string) bool {
|
|
|
|
for _, c := range s {
|
|
|
|
if c <= ' ' || c > 127 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if strings.ContainsRune("()<>@,;:\\\"/[]?={}", c) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func isValidValue(s string) bool {
|
|
|
|
for _, c := range s {
|
|
|
|
// HTTP specification allows for more technically, but we don't want to escape things.
|
|
|
|
if c < ' ' || c > 127 || c == '"' {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
2023-10-04 14:50:37 +03:00
|
|
|
|
2025-03-03 18:06:41 +03:00
|
|
|
func (h *Handler) reqLogger(ctx context.Context) *zap.Logger {
|
|
|
|
return utils.GetReqLogOrDefault(ctx, h.log)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *Handler) logAndSendError(ctx context.Context, c *fasthttp.RequestCtx, msg string, err error, additional ...zap.Field) {
|
|
|
|
utils.GetReqLogOrDefault(ctx, h.log).Error(msg,
|
|
|
|
append([]zap.Field{zap.Error(err), logs.TagField(logs.TagDatapath)}, additional...)...)
|
2023-10-04 14:50:37 +03:00
|
|
|
|
2025-03-03 18:06:41 +03:00
|
|
|
msg, code := formErrorResponse(err)
|
|
|
|
ResponseError(c, msg, code)
|
2023-10-04 14:50:37 +03:00
|
|
|
}
|
2024-09-18 07:35:26 +03:00
|
|
|
|
|
|
|
func newAddress(cnr cid.ID, obj oid.ID) oid.Address {
|
|
|
|
var addr oid.Address
|
|
|
|
addr.SetContainer(cnr)
|
|
|
|
addr.SetObject(obj)
|
|
|
|
return addr
|
|
|
|
}
|
2025-01-09 12:28:38 +03:00
|
|
|
|
2024-12-06 15:01:16 +03:00
|
|
|
// setIfNotExist sets key value to map if key is not present yet.
|
|
|
|
func setIfNotExist(m map[string]string, key, value string) {
|
|
|
|
if _, ok := m[key]; !ok {
|
|
|
|
m[key] = value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-01-09 12:28:38 +03:00
|
|
|
func ResponseError(r *fasthttp.RequestCtx, msg string, code int) {
|
|
|
|
r.Error(msg+"\n", code)
|
|
|
|
}
|
|
|
|
|
2025-03-03 18:06:41 +03:00
|
|
|
func formErrorResponse(err error) (string, int) {
|
2025-01-09 12:28:38 +03:00
|
|
|
switch {
|
2025-03-03 18:06:41 +03:00
|
|
|
case errors.Is(err, ErrAccessDenied):
|
|
|
|
return fmt.Sprintf("Storage Access Denied:\n%v", err), fasthttp.StatusForbidden
|
|
|
|
case errors.Is(err, layer.ErrNodeAccessDenied):
|
|
|
|
return fmt.Sprintf("Tree Access Denied:\n%v", err), fasthttp.StatusForbidden
|
2025-01-09 12:28:38 +03:00
|
|
|
case errors.Is(err, ErrQuotaLimitReached):
|
2025-03-03 18:06:41 +03:00
|
|
|
return fmt.Sprintf("Quota Reached:\n%v", err), fasthttp.StatusConflict
|
|
|
|
case errors.Is(err, ErrContainerNotFound):
|
|
|
|
return fmt.Sprintf("Container Not Found:\n%v", err), fasthttp.StatusNotFound
|
|
|
|
case errors.Is(err, ErrObjectNotFound):
|
|
|
|
return fmt.Sprintf("Object Not Found:\n%v", err), fasthttp.StatusNotFound
|
|
|
|
case errors.Is(err, layer.ErrNodeNotFound):
|
|
|
|
return fmt.Sprintf("Tree Node Not Found:\n%v", err), fasthttp.StatusNotFound
|
|
|
|
case errors.Is(err, ErrGatewayTimeout):
|
|
|
|
return fmt.Sprintf("Gateway Timeout:\n%v", err), fasthttp.StatusGatewayTimeout
|
2025-01-09 12:28:38 +03:00
|
|
|
default:
|
2025-03-03 18:06:41 +03:00
|
|
|
return fmt.Sprintf("Bad Request:\n%v", err), fasthttp.StatusBadRequest
|
2025-01-09 12:28:38 +03:00
|
|
|
}
|
|
|
|
}
|