Simple API to access files using link
This commit is contained in:
commit
5f0f91adcf
70
.gitea/workflows/build.yaml
Normal file
70
.gitea/workflows/build.yaml
Normal file
@ -0,0 +1,70 @@
|
||||
name: Actions Build Docker Image
|
||||
run-name: ${{ gitea.actor }} is building new image 🚀
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
Build-Docker-Image:
|
||||
runs-on: soaska
|
||||
steps:
|
||||
- run: echo "🎉 The job was automatically triggered by a ${{ gitea.event_name }} event."
|
||||
- name: Install Node.js
|
||||
run: |
|
||||
apk add --no-cache nodejs
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v3
|
||||
- name: List files in the repository
|
||||
run: |
|
||||
ls ${{ gitea.workspace }}
|
||||
- run: echo "🍏 This job's status is ${{ job.status }}."
|
||||
- name: Install Docker
|
||||
run: |
|
||||
apk add --no-cache docker
|
||||
- name: Start Docker service
|
||||
run: |
|
||||
dockerd &
|
||||
sleep 5
|
||||
docker info
|
||||
- name: Build Dockerfile
|
||||
run: |
|
||||
docker build -t $(basename ${{ github.repository }}) .
|
||||
- name: Upload Docker image to soaska.ru
|
||||
run: |
|
||||
package_name=$(basename ${{ github.repository }})
|
||||
branch_name=$(git rev-parse --abbrev-ref HEAD)
|
||||
|
||||
docker login -u ${{ secrets.username }} -p ${{ secrets.password }} soaska.ru
|
||||
docker tag $package_name soaska.ru/soaska/$package_name:$branch_name
|
||||
docker tag $package_name soaska.ru/soaska/$package_name:latest
|
||||
docker push soaska.ru/soaska/$package_name:$branch_name
|
||||
docker push soaska.ru/soaska/$package_name:latest
|
||||
Build-Binary:
|
||||
runs-on: soaska
|
||||
steps:
|
||||
- run: echo "🎉 The job was automatically triggered by a ${{ gitea.event_name }} event."
|
||||
- name: Install Node.js
|
||||
run: |
|
||||
apk add --no-cache nodejs
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v3
|
||||
- name: List files in the repository
|
||||
run: |
|
||||
ls ${{ gitea.workspace }}
|
||||
- run: echo "🍏 This job's status is ${{ job.status }}."
|
||||
- name: Install go
|
||||
run: |
|
||||
apk add --no-cache go
|
||||
- name: Install go dependencies
|
||||
run: |
|
||||
go mod download
|
||||
- name: Build Binary
|
||||
run: |
|
||||
go build -o $(basename ${{ gitea.repository }}) .
|
||||
- name: Upload binary to soaska.ru
|
||||
run: |
|
||||
package_name=$(basename ${{ gitea.repository }})
|
||||
branch_name=$(git rev-parse --abbrev-ref HEAD)
|
||||
current_date=$(date +%Y-%m-%d-%H-%M-%S)
|
||||
|
||||
curl --user ${{ secrets.username }}:${{ secrets.password }} \
|
||||
--upload-file $package_name \
|
||||
https://soaska.ru/api/packages/${{ secrets.username }}/generic/$package_name-$branch_name/¤t_date/$package_name
|
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
.env
|
||||
.vscode
|
||||
readme.md
|
16
Dockerfile
Normal file
16
Dockerfile
Normal file
@ -0,0 +1,16 @@
|
||||
# Stage 1: Build the Rod application
|
||||
FROM golang AS builder
|
||||
|
||||
WORKDIR /app
|
||||
COPY go.mod go.sum /app/
|
||||
RUN go mod download
|
||||
|
||||
COPY *.go /app/
|
||||
|
||||
## RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .
|
||||
|
||||
# Stage 2: Use a slim image for the runnable container
|
||||
FROM alpine as runtime
|
||||
WORKDIR /root/
|
||||
COPY --from=builder /app/main .
|
||||
CMD ["./main"]
|
6
example.env
Normal file
6
example.env
Normal file
@ -0,0 +1,6 @@
|
||||
# Примеры переменных
|
||||
S3_ACCESS_KEY_ID=your_access_key_id
|
||||
S3_SECRET_ACCESS_KEY=your_secret_access_key
|
||||
S3_BUCKET_NAME=your_bucket_name
|
||||
S3_ENDPOINT_URL=your_endpoint
|
||||
PORT=8080
|
20
go.mod
Normal file
20
go.mod
Normal file
@ -0,0 +1,20 @@
|
||||
module soaska.ru/soaska/MinIO-Share-S3
|
||||
|
||||
go 1.21.6
|
||||
|
||||
require (
|
||||
github.com/gorilla/mux v1.8.1
|
||||
github.com/minio/minio-go v6.0.14+incompatible
|
||||
)
|
||||
|
||||
require github.com/stretchr/testify v1.8.4 // indirect
|
||||
|
||||
require (
|
||||
github.com/go-ini/ini v1.67.0 // indirect
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
golang.org/x/crypto v0.18.0 // indirect
|
||||
golang.org/x/net v0.20.0 // indirect
|
||||
golang.org/x/sys v0.16.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
)
|
26
go.sum
Normal file
26
go.sum
Normal file
@ -0,0 +1,26 @@
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
|
||||
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/minio/minio-go v6.0.14+incompatible h1:fnV+GD28LeqdN6vT2XdGKW8Qe/IfjJDswNVuni6km9o=
|
||||
github.com/minio/minio-go v6.0.14+incompatible/go.mod h1:7guKYtitv8dktvNUGrhzmNlA5wrAABTQXCoesZdFQO8=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
128
run.go
Normal file
128
run.go
Normal file
@ -0,0 +1,128 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/joho/godotenv"
|
||||
"github.com/minio/minio-go"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Get environment variables
|
||||
accessKeyID, secretAccessKey, bucketName, endpoint, port := getEnv()
|
||||
|
||||
// Initialize MinIO client
|
||||
minioClient, err := minio.New(endpoint, accessKeyID, secretAccessKey, true)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Create a new router
|
||||
router := mux.NewRouter()
|
||||
|
||||
// Define the file handler
|
||||
router.HandleFunc("/{path:.*}", func(w http.ResponseWriter, r *http.Request) {
|
||||
log.Printf("Received request: %s %s", r.Method, r.RequestURI)
|
||||
vars := mux.Vars(r)
|
||||
path := vars["path"]
|
||||
|
||||
log.Print("Path: ", path)
|
||||
|
||||
// Get the file from S3
|
||||
object, err := minioClient.GetObject(bucketName, path, minio.GetObjectOptions{})
|
||||
if err != nil {
|
||||
if minio.ToErrorResponse(err).Code == "NoSuchKey" {
|
||||
log.Printf("Object not found in S3: %s", err)
|
||||
http.Error(w, "Object not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
log.Printf("Error getting object from S3: %s", err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Get the object info
|
||||
info, err := object.Stat()
|
||||
if err != nil {
|
||||
if minio.ToErrorResponse(err).Code == "NoSuchKey" {
|
||||
log.Printf("Object not found in S3: %s", err)
|
||||
http.Error(w, "Object not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
log.Printf("Error getting object info: %s", err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Set the content type header
|
||||
contentType := info.ContentType
|
||||
w.Header().Set("Content-Type", contentType)
|
||||
|
||||
// Copy the file to the response writer
|
||||
_, err = io.Copy(w, object)
|
||||
if err != nil {
|
||||
log.Printf("Error copying file to response writer: %s", err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}).Methods("GET")
|
||||
|
||||
router.Use(loggingMiddleware)
|
||||
|
||||
// Start the server
|
||||
|
||||
if port == "" {
|
||||
port = "8080"
|
||||
}
|
||||
addr := fmt.Sprintf(":%s", port)
|
||||
log.Printf("Server listening on %s", addr)
|
||||
log.Fatal(http.ListenAndServe(addr, router))
|
||||
}
|
||||
|
||||
func getEnv() (string, string, string, string, string) {
|
||||
err := godotenv.Load()
|
||||
if err != nil {
|
||||
log.Fatal("Error loading .env file")
|
||||
}
|
||||
|
||||
// Get environment variables
|
||||
port := os.Getenv("PORT")
|
||||
accessKeyID := os.Getenv("S3_ACCESS_KEY_ID")
|
||||
secretAccessKey := os.Getenv("S3_SECRET_ACCESS_KEY")
|
||||
bucketName := os.Getenv("S3_BUCKET_NAME")
|
||||
endpoint := os.Getenv("S3_ENDPOINT_URL")
|
||||
|
||||
return accessKeyID, secretAccessKey, bucketName, endpoint, port
|
||||
}
|
||||
|
||||
func loggingMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
startTime := time.Now()
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
|
||||
duration := time.Since(startTime)
|
||||
log.Printf("Processed request: %s %s. Duration: %v\n", r.Method, r.RequestURI, duration)
|
||||
})
|
||||
}
|
||||
|
||||
func GetObjectList(bucketName string, minioClient *minio.Client) ([]string, error) {
|
||||
var objectList []string
|
||||
|
||||
// Get the list of objects
|
||||
objectCh := minioClient.ListObjects(bucketName, "", true, nil)
|
||||
for object := range objectCh {
|
||||
if object.Err != nil {
|
||||
return nil, object.Err
|
||||
}
|
||||
objectList = append(objectList, object.Key)
|
||||
}
|
||||
|
||||
return objectList, nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user