-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhandlers.go
More file actions
203 lines (181 loc) · 6.39 KB
/
Copy pathhandlers.go
File metadata and controls
203 lines (181 loc) · 6.39 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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
package main
// handlers module holds all HTTP handlers functions
//
// Copyright (c) 2025 - Valentin Kuznetsov <vkuznet@gmail.com>
//
import (
"crypto/md5"
"encoding/base64"
"encoding/hex"
"errors"
"net/http"
"os"
"path/filepath"
"strings"
"time"
services "github.com/CHESSComputing/golib/services"
"github.com/gin-gonic/gin"
)
// UploadPayload define structure of HTTP POST request
type UploadPayload struct {
DID string `json:"did"`
File string `json:"file"`
}
// DataDirsHandler handles GET HTTP requests
func DataDirsHandler(c *gin.Context) {
// we return all dids registered in data hub
dirs, err := ListDirs(StorageDir)
if err != nil {
resp := services.Response("DataHub", http.StatusBadRequest, services.ServiceError, err)
c.JSON(http.StatusBadRequest, resp)
return
}
c.JSON(http.StatusOK, dirs)
return
}
// DataHandler handles GET HTTP requests
func DataHandler(c *gin.Context) {
didhash := c.Param("didhash")
if didhash == "" {
// we return all dids registered in data hub
dirs, err := ListDirs(StorageDir)
if err != nil {
resp := services.Response("DataHub", http.StatusBadRequest, services.ServiceError, err)
c.JSON(http.StatusBadRequest, resp)
return
}
c.JSON(http.StatusOK, dirs)
return
}
filepathParam := c.Param("filepath")
path := filepath.Join(StorageDir, didhash, filepath.Clean(filepathParam))
// get info about our path
_, err := os.Stat(path)
if err != nil {
resp := services.Response("DataHub", http.StatusBadRequest, services.ServiceError, err)
c.JSON(http.StatusBadRequest, resp)
return
}
if path == "" {
resp := services.Response("DataHub", http.StatusBadRequest, services.ServiceError, err)
c.JSON(http.StatusBadRequest, resp)
return
}
// Add NO-CACHE headers to show all the time newly added files
c.Writer.Header().Set("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0")
c.Writer.Header().Set("Pragma", "no-cache") // for older browsers
c.Writer.Header().Set("Expires", "0") // proxies treat this as expired
c.Writer.Header().Set("Last-Modified", time.Now().UTC().Format(http.TimeFormat))
// Serve file content if it's a file
http.ServeFile(c.Writer, c.Request, path)
}
// UploadHandler handles GET HTTP requests
func UploadHandler(c *gin.Context) {
var payload UploadPayload
// Parse incoming JSON
if err := c.ShouldBindJSON(&payload); err != nil {
resp := services.Response("DataHub", http.StatusBadRequest, services.ServiceError, err)
c.JSON(http.StatusBadRequest, resp)
return
}
if payload.DID == "" || payload.File == "" {
resp := services.Response("DataHub", http.StatusBadRequest, services.ServiceError, errors.New("missing did or file"))
c.JSON(http.StatusBadRequest, resp)
return
}
// we need to convert did into md5 hash
sum := md5.Sum([]byte(payload.DID))
hash := hex.EncodeToString(sum[:])
targetDir := filepath.Join(StorageDir, hash)
if err := os.MkdirAll(targetDir, 0755); err != nil {
resp := services.Response("DataHub", http.StatusInternalServerError, services.ServiceError, err)
c.JSON(http.StatusInternalServerError, resp)
return
}
// Determine if `file` is base64 or path to file
var tmpFilePath string
if _, err := os.Stat(payload.File); err == nil {
tmpFilePath = payload.File // user passed existing path
} else {
// assume base64-encoded content
tmpFile, err := os.CreateTemp("", "upload-*")
if err != nil {
resp := services.Response("DataHub", http.StatusInternalServerError, services.ServiceError, err)
c.JSON(http.StatusInternalServerError, resp)
return
}
defer tmpFile.Close()
decoded, err := base64.StdEncoding.DecodeString(payload.File)
if err != nil {
resp := services.Response("DataHub", http.StatusBadRequest, services.ServiceError, err)
c.JSON(http.StatusBadRequest, resp)
return
}
if _, err = tmpFile.Write(decoded); err != nil {
resp := services.Response("DataHub", http.StatusInternalServerError, services.ServiceError, err)
c.JSON(http.StatusInternalServerError, resp)
return
}
tmpFilePath = tmpFile.Name()
}
// Detect file type by extension
switch {
case strings.HasSuffix(tmpFilePath, ".zip"):
if err := extractZIP(tmpFilePath, targetDir); err != nil {
resp := services.Response("DataHub", http.StatusInternalServerError, services.ServiceError, err)
c.JSON(http.StatusInternalServerError, resp)
return
}
case strings.HasSuffix(tmpFilePath, ".tar"):
if err := extractTAR(tmpFilePath, targetDir); err != nil {
resp := services.Response("DataHub", http.StatusInternalServerError, services.ServiceError, err)
c.JSON(http.StatusInternalServerError, resp)
return
}
case strings.HasSuffix(tmpFilePath, ".tar.gz") || strings.HasSuffix(tmpFilePath, ".tgz"):
if err := extractTARGZ(tmpFilePath, targetDir); err != nil {
resp := services.Response("DataHub", http.StatusInternalServerError, services.ServiceError, err)
c.JSON(http.StatusInternalServerError, resp)
return
}
default:
// regular file — copy to target dir
dest := filepath.Join(targetDir, filepath.Base(tmpFilePath))
if err := copyFile(tmpFilePath, dest); err != nil {
resp := services.Response("DataHub", http.StatusInternalServerError, services.ServiceError, err)
c.JSON(http.StatusInternalServerError, resp)
return
}
}
resp := services.Response("DataHub", http.StatusOK, services.OK, nil)
c.JSON(http.StatusOK, resp)
}
// DeleteHandler handles DELETE /delete/:did requests
func DeleteHandler(c *gin.Context) {
var err error
didhash := c.Param("didhash")
if didhash == "" {
resp := services.Response("DataHub", http.StatusBadRequest, services.ServiceError, errMissingParam("didhash"))
c.JSON(http.StatusBadRequest, resp)
return
}
targetDir := filepath.Join(StorageDir, didhash)
// Check if directory exists
if _, err = os.Stat(targetDir); os.IsNotExist(err) {
resp := services.Response("DataHub", http.StatusNotFound, services.ServiceError, errNotFoundDir(targetDir))
c.JSON(http.StatusNotFound, resp)
return
} else if err != nil {
resp := services.Response("DataHub", http.StatusInternalServerError, services.ServiceError, err)
c.JSON(http.StatusInternalServerError, resp)
return
}
// Remove directory recursively
if err = os.RemoveAll(targetDir); err != nil {
resp := services.Response("DataHub", http.StatusInternalServerError, services.ServiceError, err)
c.JSON(http.StatusInternalServerError, resp)
return
}
resp := services.Response("DataHub", http.StatusOK, services.OK, nil)
c.JSON(http.StatusOK, resp)
}