initial
This commit is contained in:
commit
459b87480e
6 changed files with 189 additions and 0 deletions
20
Dockerfile
Normal file
20
Dockerfile
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
FROM gitrepo.ru/base/go:latest AS go
|
||||||
|
|
||||||
|
COPY go.mod go.sum ./
|
||||||
|
|
||||||
|
RUN go mod download
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN go generate && CGO_ENABLED=0 GOOS=linux go build -o nixshare
|
||||||
|
|
||||||
|
FROM scratch
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY --from=go /app/nixshare ./nixshare
|
||||||
|
|
||||||
|
EXPOSE 8000
|
||||||
|
|
||||||
|
CMD ["./nixshare"]
|
8
go.mod
Normal file
8
go.mod
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
module gitrepo.ru/neonxp/nixshare
|
||||||
|
|
||||||
|
go 1.23.0
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/google/uuid v1.6.0
|
||||||
|
golang.org/x/sync v0.8.0
|
||||||
|
)
|
4
go.sum
Normal file
4
go.sum
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||||
|
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
98
main.go
Normal file
98
main.go
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"flag"
|
||||||
|
"io/fs"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"path/filepath"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
host string
|
||||||
|
listen string
|
||||||
|
path string
|
||||||
|
ttl time.Duration
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
flag.StringVar(&host, "host", "https://nixshare.ru/", "host of nixshare")
|
||||||
|
flag.StringVar(&listen, "listen", ":8000", "port to listen")
|
||||||
|
flag.StringVar(&path, "path", "./storage", "storage directory")
|
||||||
|
flag.DurationVar(&ttl, "ttl", 24*time.Hour, "time to delete uploaded file")
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
r := http.NewServeMux()
|
||||||
|
|
||||||
|
r.Handle("POST /upload", http.HandlerFunc(uploadHandler))
|
||||||
|
r.Handle("/", http.FileServer(http.Dir(path)))
|
||||||
|
|
||||||
|
srv := http.Server{
|
||||||
|
Addr: listen,
|
||||||
|
Handler: r,
|
||||||
|
}
|
||||||
|
|
||||||
|
eg, egCtx := errgroup.WithContext(ctx)
|
||||||
|
|
||||||
|
eg.Go(func() error {
|
||||||
|
<-egCtx.Done()
|
||||||
|
srv.Close()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
eg.Go(func() error {
|
||||||
|
if err := srv.ListenAndServe(); err != http.ErrServerClosed {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
eg.Go(func() error {
|
||||||
|
timer := time.NewTimer(1 * time.Minute)
|
||||||
|
defer timer.Stop()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-timer.C:
|
||||||
|
now := time.Now()
|
||||||
|
err := filepath.Walk(path, func(p string, info fs.FileInfo, err error) error {
|
||||||
|
if info == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if info.IsDir() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if now.Sub(info.ModTime()).Seconds() > ttl.Seconds() {
|
||||||
|
log.Println("delete old file:", p)
|
||||||
|
if err := os.Remove(p); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
case <-egCtx.Done():
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if err := eg.Wait(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
13
storage/index.html
Normal file
13
storage/index.html
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>NixShare</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre>
|
||||||
|
curl -d @FILENAME https://nixshare.ru/upload
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
46
upload.go
Normal file
46
upload.go
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
func uploadHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
uid := uuid.New().String()
|
||||||
|
section := string(uid[len(uid)-1])
|
||||||
|
if err := os.MkdirAll(filepath.Join(path, section), 0777); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
http.Error(w, "can't create storage dir", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fp, err := os.Create(filepath.Join(path, section, uid))
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
http.Error(w, "can't create storage file", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer fp.Close()
|
||||||
|
if _, err := io.Copy(fp, r.Body); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
http.Error(w, "can't upload storage file", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
h := w.Header()
|
||||||
|
h.Set("Content-Type", "text/plain; charset=utf-8")
|
||||||
|
h.Set("X-Content-Type-Options", "nosniff")
|
||||||
|
w.WriteHeader(http.StatusCreated)
|
||||||
|
u, err := url.JoinPath(host, section, uid)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
http.Error(w, "can't get file url", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Fprintln(w, u)
|
||||||
|
}
|
Loading…
Reference in a new issue