Files
soft_usite/rest/controllers/api/oss_helpers.go
T
Lizandro GuarnizoandClaude Opus 5 17ed57cb56 fix(vcard): decir por qué falla la subida a OSS, y no armar la clave con texto crudo del cliente
El sistema que consume /v2/vcard/qr-url solo recibía "Error subiendo archivo a
OSS": el motivo quedaba en nuestro log y del otro lado no había nada que hacer
con eso. Ahora la respuesta incluye el error real del proveedor —es una API
entre servidores y el que llama ya conoce la config de OSS que mandó— y el log
dice además qué clave se intentó subir.

La clave del objeto se armaba con el nombre tal como venía en el body. Un
nombre con "/" o con caracteres que OSS no acepta producía justamente ese
error genérico. Ahora se limpia.

El mismo nombre crudo se usaba para el archivo temporal (/tmp/<nombre>.webp),
o sea escritura de archivos en una ruta que elegía quien llamaba. Se fue
entero: los tres endpoints suben desde memoria con UploadFromReader, que
además saca el paso a disco y su limpieza.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 20:04:34 -05:00

69 lines
1.8 KiB
Go

package controllers
import (
"encoding/json"
"strings"
"github.com/gofiber/fiber/v2"
"github.com/sujit-baniya/fiber-boilerplate/pkg/models"
"github.com/sujit-baniya/fiber-boilerplate/pkg/services"
)
// getOSSFromBody creates an OSSProvider from the oss_api_id in the request body.
// If oss_api_id is missing, it falls back to the last active config (legacy behavior).
func getOSSFromBody(c *fiber.Ctx) (services.OSSProvider, error) {
var req struct {
OssAPIID *uint `json:"oss_api_id"`
}
if err := json.Unmarshal(c.Body(), &req); err != nil {
req.OssAPIID = nil
}
if req.OssAPIID != nil {
return services.NewOSSProviderByID(*req.OssAPIID)
}
return services.NewOSSProviderFromDB()
}
// getOSSFromQuery creates an OSSProvider from the oss_api_id query param.
// If missing, falls back to last active config.
func getOSSFromQuery(c *fiber.Ctx) (services.OSSProvider, error) {
id := c.QueryInt("oss_api_id", 0)
if id > 0 {
return services.NewOSSProviderByID(uint(id))
}
lastActive, err := models.GetLastActiveOssApi()
if err != nil {
return nil, err
}
return services.NewOSSProvider(lastActive)
}
// claveObjetoSegura arma una clave de objeto a partir de texto que viene del
// cliente. Sin esto, un nombre con "/" o con caracteres de control produce una
// clave que OSS rechaza — y el que llama solo ve "error subiendo a OSS".
func claveObjetoSegura(nombre string) string {
nombre = strings.TrimSpace(nombre)
limpio := strings.Map(func(r rune) rune {
switch {
case r >= 'a' && r <= 'z', r >= 'A' && r <= 'Z', r >= '0' && r <= '9':
return r
case r == '-', r == '_', r == '.':
return r
case r == ' ':
return '_'
default:
return -1
}
}, nombre)
limpio = strings.Trim(limpio, "._-")
if limpio == "" {
return "sin-nombre"
}
if len(limpio) > 80 {
limpio = limpio[:80]
}
return limpio
}