package main import ( "context" "io" "log" "math/rand" "net/http" "os" "strings" "text/template" "time" "github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7/pkg/credentials" "gopkg.in/yaml.v3" ) type ImageProvider interface { GetImage() string } type LocalProvider struct{} type S3Provider struct { confHundler ConfHandler } func (p LocalProvider) GetImage() string { return GetRandImg() } func (p S3Provider) GetImage() string { return p.confHundler.GetRandImgS3() } func GetPicsArray() []string { files, err := os.ReadDir("images") if err != nil { log.Printf("Ошибка чтения директории: %v", err) return []string{} } if len(files) == 0 { return []string{"no images"} } var filesNames = make([]string, len(files)) for i, file := range files { filesNames[i] = string("images/" + file.Name()) } return filesNames } func (conf *ConfHandler) GetRandImgS3() string { picsArray := GetObjectsFilenames(conf.ConfigHandler, *conf.minioClient) return picsArray[rand.Intn(len(picsArray))] } func GetRandImg() string { picsArray := GetPicsArray() if len(picsArray) == 0 { return "" } return picsArray[rand.Intn(len(picsArray))] } func ReturnPicFilename(provider ImageProvider) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { image := provider.GetImage() io.Copy(w, strings.NewReader(image)) log.Println("Картинка отдана") } } func ReturnHTML(provider ImageProvider) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { htmlOpen, err := template.ParseFiles("dist/index.html") if err != nil { log.Println(err.Error()) return } image := provider.GetImage() if err := htmlOpen.Execute(w, image); err != nil { log.Printf("Ошибка рендеринга: %v", err) } } } type Config struct { UseS3 bool `yaml:"use_s3"` Address string `yaml:"address"` Bucket string `yaml:"bucket"` AccessKey string `yaml:"access_key"` SecretKey string `yaml:"secret_key"` } type ConfHandler struct { ConfigHandler Config minioClient *minio.Client } func InitConf(filename string) Config { var conf Config configFile, _ := os.ReadFile(filename) err := yaml.Unmarshal(configFile, &conf) if err != nil { log.Fatal(err) } return conf } func GetObjectsFilenames(conf Config, minioClient minio.Client) []string { ctx, cancel := context.WithCancel(context.Background()) defer cancel() objectCh := minioClient.ListObjects(ctx, conf.Bucket, minio.ListObjectsOptions{Recursive: false}) log.Println(objectCh) objectsKeyArr := []string{} for object := range objectCh { if object.Err != nil { log.Println(object.Err) } objectsKeyArr = append(objectsKeyArr, "https://"+conf.Address+"/"+conf.Bucket+"/"+object.Key) } return objectsKeyArr } func main() { log.Println("Server Start") rand.New(rand.NewSource(time.Now().UnixNano())) conf := InitConf("config.yaml") imagesDir := http.FileServer(http.Dir("images")) staticDir := http.FileServer(http.Dir("dist/assets")) http.Handle("/images/", http.StripPrefix("/images/", imagesDir)) http.Handle("/assets/", http.StripPrefix("/assets/", staticDir)) var provider ImageProvider if !conf.UseS3 { provider = LocalProvider{} } else { minioClient, err := minio.New(conf.Address, &minio.Options{ Creds: credentials.NewStaticV4(conf.AccessKey, conf.SecretKey, ""), Secure: true, }) if err != nil { log.Fatalln(err) } provider = S3Provider{ confHundler: ConfHandler{ ConfigHandler: conf, minioClient: minioClient, }, } } http.HandleFunc("/rand", ReturnPicFilename(provider)) http.HandleFunc("/", ReturnHTML(provider)) http.ListenAndServe(":3666", nil) }