2023-08-31 08:37:03 +00:00
|
|
|
package handler
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/logs"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/response"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/tokens"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
2023-10-04 11:50:37 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
|
2024-09-18 04:35:26 +00:00
|
|
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
2024-10-10 08:59:53 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
2024-09-18 04:35:26 +00:00
|
|
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
2023-08-31 08:37:03 +00:00
|
|
|
"github.com/valyala/fasthttp"
|
|
|
|
"go.uber.org/zap"
|
|
|
|
)
|
|
|
|
|
|
|
|
type request struct {
|
|
|
|
*fasthttp.RequestCtx
|
|
|
|
log *zap.Logger
|
|
|
|
}
|
|
|
|
|
2024-12-13 13:00:31 +00:00
|
|
|
func newRequest(ctx *fasthttp.RequestCtx, log *zap.Logger) request {
|
|
|
|
return request{
|
|
|
|
RequestCtx: ctx,
|
|
|
|
log: log,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-31 08:37:03 +00:00
|
|
|
func (r *request) handleFrostFSErr(err error, start time.Time) {
|
|
|
|
logFields := []zap.Field{
|
|
|
|
zap.Stringer("elapsed", time.Since(start)),
|
|
|
|
zap.Error(err),
|
|
|
|
}
|
|
|
|
statusCode, msg, additionalFields := response.FormErrorResponse("could not receive object", err)
|
|
|
|
logFields = append(logFields, additionalFields...)
|
|
|
|
|
|
|
|
r.log.Error(logs.CouldNotReceiveObject, logFields...)
|
|
|
|
response.Error(r.RequestCtx, msg, statusCode)
|
|
|
|
}
|
|
|
|
|
|
|
|
func bearerToken(ctx context.Context) *bearer.Token {
|
|
|
|
if tkn, err := tokens.LoadBearerToken(ctx); err == nil {
|
|
|
|
return tkn
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-09-26 14:32:27 +00:00
|
|
|
func isDir(name string) bool {
|
|
|
|
return strings.HasSuffix(name, "/")
|
|
|
|
}
|
|
|
|
|
2024-10-10 08:59:53 +00:00
|
|
|
func isObjectID(s string) bool {
|
|
|
|
var objID oid.ID
|
|
|
|
return objID.DecodeString(s) == nil
|
|
|
|
}
|
|
|
|
|
2024-09-26 14:32:27 +00:00
|
|
|
func isContainerRoot(key string) bool {
|
|
|
|
return key == ""
|
|
|
|
}
|
|
|
|
|
2024-10-10 08:59:53 +00: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 14:32:27 +00:00
|
|
|
}
|
2024-10-10 08:59:53 +00:00
|
|
|
return result
|
2024-09-26 14:32:27 +00:00
|
|
|
}
|
|
|
|
|
2023-08-31 08:37:03 +00: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 11:50:37 +00:00
|
|
|
|
|
|
|
func logAndSendBucketError(c *fasthttp.RequestCtx, log *zap.Logger, err error) {
|
|
|
|
log.Error(logs.CouldntGetBucket, zap.Error(err))
|
|
|
|
|
|
|
|
if client.IsErrContainerNotFound(err) {
|
|
|
|
response.Error(c, "Not Found", fasthttp.StatusNotFound)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
response.Error(c, "could not get bucket: "+err.Error(), fasthttp.StatusBadRequest)
|
|
|
|
}
|
2024-09-18 04:35:26 +00:00
|
|
|
|
|
|
|
func newAddress(cnr cid.ID, obj oid.ID) oid.Address {
|
|
|
|
var addr oid.Address
|
|
|
|
addr.SetContainer(cnr)
|
|
|
|
addr.SetObject(obj)
|
|
|
|
return addr
|
|
|
|
}
|