Repository navigation
Expand file tree
/
Copy pathmain.go
More file actions
144 lines (121 loc) · 3.83 KB
/
Copy pathmain.go
File metadata and controls
144 lines (121 loc) · 3.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package main
import (
"flag"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"strings"
"github.com/sirupsen/logrus"
)
var (
port string
filesDir string
ipAddress string
maxUploadSize int64
)
func main() {
flag.StringVar(&port, "port", "8080", "Port for launching the web server")
flag.StringVar(&filesDir, "dir", "./files", "Directory for saving files")
flag.StringVar(&ipAddress, "ip", "0.0.0.0", "IP address for launching the server")
flag.Int64Var(&maxUploadSize, "max-upload-size", 10<<20, "Maximum upload file size in bytes")
flag.Parse()
// Logger setup
log := logrus.New()
log.Formatter = &logrus.TextFormatter{
FullTimestamp: true,
ForceColors: true,
}
log.Out = os.Stdout
// Checking and creating directory for files
if _, err := os.Stat(filesDir); os.IsNotExist(err) {
if err := os.MkdirAll(filesDir, os.ModePerm); err != nil {
log.Fatalf("Failed to create directory: %v", err)
}
}
log.Println("Starting server...")
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
handleRequests(w, r, log)
})
fullAddress := fmt.Sprintf("%s:%s", ipAddress, port)
log.Printf("Server running on http://%s", fullAddress)
log.Printf("Upload endpoint: http://%s/api/filehandler/", fullAddress)
if err := http.ListenAndServe(fullAddress, nil); err != nil {
log.Fatalf("Server startup error: %v", err)
}
}
func handleRequests(w http.ResponseWriter, r *http.Request, log *logrus.Logger) {
log.WithFields(logrus.Fields{
"method": r.Method,
"path": r.URL.Path,
"ip": r.RemoteAddr,
}).Info("Request received")
// Modifying the condition to account for all requests starting with /api/filehandler/
if r.Method == "POST" && strings.HasPrefix(r.URL.Path, "/api/filehandler/") {
uploadFileHandler(w, r, log)
return
}
filePath := filepath.Join(filesDir, filepath.Clean(r.URL.Path))
if _, err := os.Stat(filePath); os.IsNotExist(err) {
http.NotFound(w, r)
return
}
http.ServeFile(w, r, filePath)
}
func uploadFileHandler(w http.ResponseWriter, r *http.Request, log *logrus.Logger) {
if r.Method != "POST" {
http.Error(w, "Only POST method is supported", http.StatusMethodNotAllowed)
return
}
// Limiting the request body size to prevent memory overflow
r.Body = http.MaxBytesReader(w, r.Body, maxUploadSize)
if err := r.ParseMultipartForm(maxUploadSize); err != nil {
log.WithFields(logrus.Fields{
"ip": r.RemoteAddr,
"err": err,
}).Error("Maximum file size exceeded")
http.Error(w, "Maximum file size exceeded", http.StatusBadRequest)
return
}
file, handler, err := r.FormFile("file")
if err != nil {
log.WithFields(logrus.Fields{
"ip": r.RemoteAddr,
"err": err,
}).Error("Error receiving file")
http.Error(w, "Error receiving file", http.StatusBadRequest)
return
}
defer file.Close()
// Extracting subpath from URL
subPath := strings.TrimPrefix(r.URL.Path, "/api/filehandler/")
if subPath == "" || strings.HasSuffix(subPath, "/") {
subPath = filepath.Join(subPath, handler.Filename) // Adding file name if subpath is empty or ends with /
}
filePath := filepath.Join(filesDir, filepath.Clean(subPath))
os.MkdirAll(filepath.Dir(filePath), os.ModePerm) // Creating all necessary directories
dst, err := os.Create(filePath)
if err != nil {
log.WithFields(logrus.Fields{
"path": filePath,
"err": err,
}).Error("Error creating file")
http.Error(w, "Error creating file", http.StatusInternalServerError)
return
}
defer dst.Close()
if _, err = io.Copy(dst, file); err != nil {
log.WithFields(logrus.Fields{
"path": filePath,
"err": err,
}).Error("Error saving file")
http.Error(w, "Error saving file", http.StatusInternalServerError)
return
}
log.WithFields(logrus.Fields{
"path": filePath,
"ip": r.RemoteAddr,
}).Info("File successfully uploaded")
fmt.Fprintf(w, "File %s uploaded successfully", handler.Filename)
}