Compare commits

...

3 commits

Author SHA1 Message Date
nquidox
c2304f6a7d update 2025-10-17 23:48:05 +03:00
nquidox
bc6621154b return etag 2025-10-17 23:47:48 +03:00
nquidox
d1542b274e switch to ubuntu 2025-10-17 23:46:34 +03:00
8 changed files with 36 additions and 30 deletions

View file

@ -1,14 +1,5 @@
FROM golang:1.25.1-alpine3.22 AS builder FROM golang:1.25.1-alpine3.22 AS builder
RUN apk add --no-cache \
bash \
curl \
git \
ca-certificates
RUN apk add --no-cache tzdata
WORKDIR /app WORKDIR /app
COPY go.mod go.sum ./ COPY go.mod go.sum ./
RUN go mod download RUN go mod download
@ -16,19 +7,11 @@ COPY . .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -ldflags="-s -w" -o main "./cmd" RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -ldflags="-s -w" -o main "./cmd"
FROM alpine:3.22 FROM ubuntu:24.04
RUN apk add --no-cache \
bash \
curl \
ca-certificates \
tzdata
COPY --from=builder /app/main /usr/local/bin/app COPY --from=builder /app/main /usr/local/bin/app
RUN chmod +x /usr/local/bin/app RUN chmod +x /usr/local/bin/app
#RUN adduser -D -s /bin/bash appuser
#USER appuser
ENTRYPOINT ["app"] ENTRYPOINT ["app"]

View file

@ -12,6 +12,7 @@ MEDIA_STORAGE_USER=
MEDIA_STORAGE_PASS= MEDIA_STORAGE_PASS=
MEDIA_STORAGE_HOST= MEDIA_STORAGE_HOST=
MEDIA_STORAGE_PORT= MEDIA_STORAGE_PORT=
MEDIA_STORAGE_SECURE=false
DB_HOST= DB_HOST=
DB_PORT= DB_PORT=

View file

@ -362,7 +362,7 @@ func (co *controller) getMerchImage(c *gin.Context) {
log.WithError(err).Error("Merch | Failed to get merch image") log.WithError(err).Error("Merch | Failed to get merch image")
return return
} }
c.JSON(http.StatusOK, ImageLink{Link: link.String()}) c.JSON(http.StatusOK, link)
} }
// @Summary Удалить (безвозвратно) картинки по merch_uuid и query параметрам // @Summary Удалить (безвозвратно) картинки по merch_uuid и query параметрам

View file

@ -56,4 +56,5 @@ type UpdateMerchDTO struct {
type ImageLink struct { type ImageLink struct {
Link string `json:"link"` Link string `json:"link"`
ETag string `json:"etag"`
} }

View file

@ -32,10 +32,10 @@ func NewHandler(deps Deps) *Handler {
"addr": media, "addr": media,
}).Debug("Merch handler constructor | Media provider") }).Debug("Merch handler constructor | Media provider")
//exists, err := media.CheckBucketExists(packageBucketName) exists, err := media.CheckBucketExists(packageBucketName)
//if err != nil || !exists { if err != nil || !exists {
// log.WithError(err).Fatal("Merch handler constructor | Failed to ensure bucket exists") log.WithError(err).Fatal("Merch handler constructor | Failed to ensure bucket exists")
//} }
return &Handler{ return &Handler{
repo: r, repo: r,

View file

@ -14,7 +14,6 @@ import (
"io" "io"
"merch-parser-api/internal/interfaces" "merch-parser-api/internal/interfaces"
"mime/multipart" "mime/multipart"
"net/url"
"path/filepath" "path/filepath"
"strings" "strings"
"time" "time"
@ -304,14 +303,14 @@ func (s *service) uploadMerchImage(ctx context.Context, userUuid, merchUuid, ima
return nil return nil
} }
func (s *service) getMerchImage(ctx context.Context, userUuid, merchUuid, imageType string) (*url.URL, error) { func (s *service) getMerchImage(ctx context.Context, userUuid, merchUuid, imageType string) (ImageLink, error) {
exists, err := s.repo.merchRecordExists(userUuid, merchUuid) exists, err := s.repo.merchRecordExists(userUuid, merchUuid)
if err != nil { if err != nil {
return nil, err return ImageLink{}, err
} }
if !exists { if !exists {
return nil, fmt.Errorf("no merch found for user %s with uuid %s", userUuid, merchUuid) return ImageLink{}, fmt.Errorf("no merch found for user %s with uuid %s", userUuid, merchUuid)
} }
var object string var object string
@ -321,10 +320,23 @@ func (s *service) getMerchImage(ctx context.Context, userUuid, merchUuid, imageT
case "full": case "full":
object = fmt.Sprintf("%s/merch/%s/full.jpg", userUuid, merchUuid) object = fmt.Sprintf("%s/merch/%s/full.jpg", userUuid, merchUuid)
default: default:
return nil, fmt.Errorf("unknown image type %s", imageType) return ImageLink{}, fmt.Errorf("unknown image type %s", imageType)
} }
return s.media.Get(ctx, s.bucketName, object, s.expires, nil) link, err := s.media.Get(ctx, s.bucketName, object, s.expires, nil)
if err != nil {
return ImageLink{}, err
}
etag, err := s.media.GetObjectEtag(ctx, s.bucketName, object)
if err != nil {
return ImageLink{}, err
}
return ImageLink{
Link: link.String(),
ETag: etag,
}, nil
} }
func (s *service) deleteMerchImage(ctx context.Context, userUuid, merchUuid string) error { func (s *service) deleteMerchImage(ctx context.Context, userUuid, merchUuid string) error {
@ -367,7 +379,7 @@ func (s *service) _uploadToStorage(params uploadImageParams) error {
if err != nil { if err != nil {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"error": err, "error": err,
"img type": "full", "img type": params.imageType,
}).Error("Merch | Failed to upload file to media storage") }).Error("Merch | Failed to upload file to media storage")
return err return err
} }

View file

@ -12,4 +12,5 @@ type MediaStorage interface {
Upload(ctx context.Context, bucket, object string, reader io.Reader, size int64) error Upload(ctx context.Context, bucket, object string, reader io.Reader, size int64) error
Get(ctx context.Context, bucket, object string, expires time.Duration, params url.Values) (*url.URL, error) Get(ctx context.Context, bucket, object string, expires time.Duration, params url.Values) (*url.URL, error)
Delete(ctx context.Context, bucket, object string) error Delete(ctx context.Context, bucket, object string) error
GetObjectEtag(ctx context.Context, bucketName, object string) (string, error)
} }

View file

@ -42,3 +42,11 @@ func (s *Service) Get(ctx context.Context, bucket, object string, expires time.D
func (s *Service) Delete(ctx context.Context, bucket, object string) error { func (s *Service) Delete(ctx context.Context, bucket, object string) error {
return s.client.RemoveObject(ctx, bucket, object, minio.RemoveObjectOptions{}) return s.client.RemoveObject(ctx, bucket, object, minio.RemoveObjectOptions{})
} }
func (s *Service) GetObjectEtag(ctx context.Context, bucketName, object string) (string, error) {
info, err := s.client.StatObject(ctx, bucketName, object, minio.StatObjectOptions{})
if err != nil {
return "", err
}
return info.ETag, nil
}