package handler import ( "context" "net/http" "path" "strconv" "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-http-gw/utils" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "github.com/valyala/fasthttp" "go.uber.org/zap" ) type request struct { *fasthttp.RequestCtx log *zap.Logger } 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 (r *request) setAttributes(attrs map[string]string) { for key, val := range attrs { r.Response.Header.Set(utils.UserAttributeHeaderPrefix+key, val) } } func (r *request) setIDs(obj object.Object) { objID, _ := obj.ID() cnrID, _ := obj.ContainerID() r.Response.Header.Set(hdrObjectID, objID.String()) r.Response.Header.Set(hdrOwnerID, obj.OwnerID().String()) r.Response.Header.Set(hdrContainerID, cnrID.String()) } func (r *request) setDisposition(shouldDownload bool, filename string) { const ( inlineDisposition = "inline" attachmentDisposition = "attachment" ) dis := inlineDisposition if shouldDownload { dis = attachmentDisposition } r.Response.Header.Set(fasthttp.HeaderContentDisposition, dis+"; filename="+path.Base(filename)) } func (r *request) setTimestamp(timestamp string) error { value, err := strconv.ParseInt(timestamp, 10, 64) if err != nil { return err } r.Response.Header.Set(fasthttp.HeaderLastModified, time.Unix(value, 0).UTC().Format(http.TimeFormat)) return nil } func bearerToken(ctx context.Context) *bearer.Token { if tkn, err := tokens.LoadBearerToken(ctx); err == nil { return tkn } return nil } 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 } 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) }