-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrpc.go
More file actions
297 lines (251 loc) · 9.7 KB
/
rpc.go
File metadata and controls
297 lines (251 loc) · 9.7 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
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
package s3
import (
"go.uber.org/zap"
)
// rpc implements the RPC interface exposed to PHP via goridge
type rpc struct {
plugin *Plugin
log *zap.Logger
}
// RegisterBucketRequest represents the request to register a new bucket dynamically
type RegisterBucketRequest struct {
Name string `json:"name"`
Server string `json:"server"`
Bucket string `json:"bucket"`
Prefix string `json:"prefix"`
Visibility string `json:"visibility"`
}
// RegisterBucketResponse represents the response from bucket registration
type RegisterBucketResponse struct {
Success bool `json:"success"`
Message string `json:"message"`
}
// ListBucketsRequest represents the request to list all buckets
type ListBucketsRequest struct{}
// ListBucketsResponse represents the response with all bucket names
type ListBucketsResponse struct {
Buckets []string `json:"buckets"`
Default string `json:"default"`
}
// WriteRequest represents a file write/upload request
type WriteRequest struct {
Bucket string `json:"bucket"`
Pathname string `json:"pathname"`
Content []byte `json:"content"`
Config map[string]string `json:"config,omitempty"`
Visibility string `json:"visibility,omitempty"`
}
// WriteResponse represents the response from a write operation
type WriteResponse struct {
Success bool `json:"success"`
Pathname string `json:"pathname"`
Size int64 `json:"size"`
LastModified int64 `json:"last_modified"`
}
// ReadRequest represents a file read/download request
type ReadRequest struct {
Bucket string `json:"bucket"`
Pathname string `json:"pathname"`
}
// ReadResponse represents the response from a read operation
type ReadResponse struct {
Content []byte `json:"content"`
Size int64 `json:"size"`
MimeType string `json:"mime_type"`
LastModified int64 `json:"last_modified"`
}
// ExistsRequest represents a file existence check request
type ExistsRequest struct {
Bucket string `json:"bucket"`
Pathname string `json:"pathname"`
}
// ExistsResponse represents the response from an exists check
type ExistsResponse struct {
Exists bool `json:"exists"`
}
// DeleteRequest represents a file deletion request
type DeleteRequest struct {
Bucket string `json:"bucket"`
Pathname string `json:"pathname"`
}
// DeleteResponse represents the response from a delete operation
type DeleteResponse struct {
Success bool `json:"success"`
}
// CopyRequest represents a file copy request
type CopyRequest struct {
SourceBucket string `json:"source_bucket"`
SourcePathname string `json:"source_pathname"`
DestBucket string `json:"dest_bucket"`
DestPathname string `json:"dest_pathname"`
Config map[string]string `json:"config,omitempty"`
Visibility string `json:"visibility,omitempty"`
}
// CopyResponse represents the response from a copy operation
type CopyResponse struct {
Success bool `json:"success"`
Pathname string `json:"pathname"`
Size int64 `json:"size"`
LastModified int64 `json:"last_modified"`
}
// MoveRequest represents a file move request (copy + delete)
type MoveRequest struct {
SourceBucket string `json:"source_bucket"`
SourcePathname string `json:"source_pathname"`
DestBucket string `json:"dest_bucket"`
DestPathname string `json:"dest_pathname"`
Config map[string]string `json:"config,omitempty"`
Visibility string `json:"visibility,omitempty"`
}
// MoveResponse represents the response from a move operation
type MoveResponse struct {
Success bool `json:"success"`
Pathname string `json:"pathname"`
Size int64 `json:"size"`
LastModified int64 `json:"last_modified"`
}
// GetMetadataRequest represents a request to get file metadata
type GetMetadataRequest struct {
Bucket string `json:"bucket"`
Pathname string `json:"pathname"`
}
// GetMetadataResponse represents file metadata
type GetMetadataResponse struct {
Size int64 `json:"size"`
MimeType string `json:"mime_type"`
LastModified int64 `json:"last_modified"`
Visibility string `json:"visibility"`
ETag string `json:"etag,omitempty"`
}
// SetVisibilityRequest represents a request to change file visibility
type SetVisibilityRequest struct {
Bucket string `json:"bucket"`
Pathname string `json:"pathname"`
Visibility string `json:"visibility"`
}
// SetVisibilityResponse represents the response from visibility change
type SetVisibilityResponse struct {
Success bool `json:"success"`
}
// GetPublicURLRequest represents a request to generate a public URL
type GetPublicURLRequest struct {
Bucket string `json:"bucket"`
Pathname string `json:"pathname"`
ExpiresIn int64 `json:"expires_in,omitempty"` // Seconds, 0 for permanent
}
// GetPublicURLResponse represents the response with a public URL
type GetPublicURLResponse struct {
URL string `json:"url"`
ExpiresAt int64 `json:"expires_at,omitempty"` // Unix timestamp
}
// ListObjectsRequest represents a request to list objects in a bucket
type ListObjectsRequest struct {
Bucket string `json:"bucket"`
Prefix string `json:"prefix,omitempty"` // Filter by prefix
Delimiter string `json:"delimiter,omitempty"` // Delimiter for grouping (e.g., "/")
MaxKeys int32 `json:"max_keys,omitempty"` // Maximum number of keys to return (default: 1000)
ContinuationToken string `json:"continuation_token,omitempty"` // Token for pagination
}
// ObjectInfo represents information about a single S3 object
type ObjectInfo struct {
Key string `json:"key"`
Size int64 `json:"size"`
LastModified int64 `json:"last_modified"` // Unix timestamp
ETag string `json:"etag"`
StorageClass string `json:"storage_class,omitempty"`
}
// CommonPrefix represents a common prefix (directory-like structure)
type CommonPrefix struct {
Prefix string `json:"prefix"`
}
// ListObjectsResponse represents the response from list objects operation
type ListObjectsResponse struct {
Objects []ObjectInfo `json:"objects"`
CommonPrefixes []CommonPrefix `json:"common_prefixes,omitempty"`
IsTruncated bool `json:"is_truncated"`
NextContinuationToken string `json:"next_continuation_token,omitempty"`
KeyCount int32 `json:"key_count"`
}
// RegisterBucket registers a new bucket dynamically via RPC
// Note: The bucket must reference an existing server from configuration
func (r *rpc) RegisterBucket(req *RegisterBucketRequest, resp *RegisterBucketResponse) error {
r.log.Debug("registering bucket via RPC",
zap.String("name", req.Name),
zap.String("server", req.Server),
zap.String("bucket", req.Bucket),
)
// Create bucket configuration from request
cfg := &BucketConfig{
Server: req.Server,
Bucket: req.Bucket,
Prefix: req.Prefix,
Visibility: req.Visibility,
}
// Get bucket manager to access server configs
bucketManager := r.plugin.GetBucketManager()
// Lock for reading servers map
bucketManager.mu.RLock()
servers := bucketManager.servers
bucketManager.mu.RUnlock()
// Validate configuration (this will check if server exists)
if err := cfg.Validate(servers); err != nil {
resp.Success = false
resp.Message = "Invalid configuration: " + err.Error()
return NewInvalidConfigError(err.Error())
}
// Register bucket
if err := bucketManager.RegisterBucket(r.plugin.ctx, req.Name, cfg); err != nil {
resp.Success = false
resp.Message = "Failed to register bucket: " + err.Error()
return err
}
resp.Success = true
resp.Message = "Bucket registered successfully"
return nil
}
// ListBuckets lists all registered buckets
func (r *rpc) ListBuckets(req *ListBucketsRequest, resp *ListBucketsResponse) error {
resp.Buckets = r.plugin.buckets.ListBuckets()
resp.Default = r.plugin.buckets.GetDefaultBucketName()
return nil
}
// Write uploads a file to S3
func (r *rpc) Write(req *WriteRequest, resp *WriteResponse) error {
return r.plugin.operations.Write(r.plugin.ctx, req, resp)
}
// Read downloads a file from S3
func (r *rpc) Read(req *ReadRequest, resp *ReadResponse) error {
return r.plugin.operations.Read(r.plugin.ctx, req, resp)
}
// Exists checks if a file exists in S3
func (r *rpc) Exists(req *ExistsRequest, resp *ExistsResponse) error {
return r.plugin.operations.Exists(r.plugin.ctx, req, resp)
}
// Delete deletes a file from S3
func (r *rpc) Delete(req *DeleteRequest, resp *DeleteResponse) error {
return r.plugin.operations.Delete(r.plugin.ctx, req, resp)
}
// Copy copies a file within or between buckets
func (r *rpc) Copy(req *CopyRequest, resp *CopyResponse) error {
return r.plugin.operations.Copy(r.plugin.ctx, req, resp)
}
// Move moves a file within or between buckets
func (r *rpc) Move(req *MoveRequest, resp *MoveResponse) error {
return r.plugin.operations.Move(r.plugin.ctx, req, resp)
}
// GetMetadata retrieves file metadata
func (r *rpc) GetMetadata(req *GetMetadataRequest, resp *GetMetadataResponse) error {
return r.plugin.operations.GetMetadata(r.plugin.ctx, req, resp)
}
// SetVisibility changes file visibility (ACL)
func (r *rpc) SetVisibility(req *SetVisibilityRequest, resp *SetVisibilityResponse) error {
return r.plugin.operations.SetVisibility(r.plugin.ctx, req, resp)
}
// GetPublicURL generates a public or presigned URL for a file
func (r *rpc) GetPublicURL(req *GetPublicURLRequest, resp *GetPublicURLResponse) error {
return r.plugin.operations.GetPublicURL(r.plugin.ctx, req, resp)
}
// ListObjects lists objects in a bucket with optional filtering
func (r *rpc) ListObjects(req *ListObjectsRequest, resp *ListObjectsResponse) error {
return r.plugin.operations.ListObjects(r.plugin.ctx, req, resp)
}