package gosqs import ( "net/http" "strings" "shared-sqs/app/interfaces" "shared-sqs/app/models" "shared-sqs/app/persistence" "shared-sqs/app/utils" log "github.com/sirupsen/logrus" ) // SetQueueAttributesV1 — устанавливает атрибуты очереди тенанта. // // Логическая схема: // 1. Разбор тела запроса (Query/JSON) → SetQueueAttributesRequest. // 2. QueueUrl обязателен → InvalidParameterValue. // 3. Тенант из контекста (SigV4 → AccessKey). // 4. Имя очереди из QueueUrl (последний сегмент) + tenant-scoped ключ. // 5. Под Lock: проверка существования очереди → QueueNotFound; // применение атрибутов с валидацией (setQueueAttributesV1); // сохранение очереди в Redis (асинхронно, маршалинг под Lock). // 6. Ответ: пустой SetQueueAttributesResponse (AWS так и отвечает). func SetQueueAttributesV1(req *http.Request) (int, interfaces.AbstractResponseBody) { requestBody := models.NewSetQueueAttributesRequest() ok := utils.REQUEST_TRANSFORMER(requestBody, req, false) if !ok { log.Error("Invalid Request - SetQueueAttributesV1") return utils.CreateErrorResponseV1("InvalidParameterValue", true) } if requestBody.QueueUrl == "" { log.Error("Missing QueueUrl - SetQueueAttributesV1") return utils.CreateErrorResponseV1("InvalidParameterValue", true) } t := getTenantFromContext(req) if t == nil { return utils.CreateErrorResponseV1("InvalidClientTokenId", true) } uriSegments := strings.Split(requestBody.QueueUrl, "/") queueName := uriSegments[len(uriSegments)-1] key := tenantQueueKey(t.AccessKey, queueName) log.Infof("Set Queue Attributes: %s (tenant: %s)", queueName, t.ID) models.SyncQueues.Lock() defer models.SyncQueues.Unlock() queue, ok := models.SyncQueues.Queues[key] if !ok { log.Warningf("Set Queue Attributes: %s, queue does not exist for tenant %s", queueName, t.ID) return utils.CreateErrorResponseV1("QueueNotFound", true) } // Список имён переданных атрибутов — для whitelist-валидации. // Query-протокол: имена видны в form (Attribute.N.Name). // JSON-протокол: структура уже разобрана из тела, список имён недоступен → nil // (whitelist-проверка пропускается, неизвестные поля отброшены парсером). var provided map[string]string if req.Header.Get("Content-Type") != "application/x-amz-json-1.0" { provided = utils.ExtractQueueAttributes(req.PostForm) } if err := setQueueAttributesV1(queue, requestBody.Attributes, provided, t.AccessKey); err != nil { return utils.CreateErrorResponseV1(err.Error(), true) } // Сохраняем атрибуты в Redis пока держим Lock (через defer) persistence.SaveQueue(key, queue) respStruct := models.SetQueueAttributesResponse{ Xmlns: models.BaseXmlns, Metadata: models.BaseResponseMetadata, } return http.StatusOK, respStruct }