s3tables: add bucket name validation and fix error handling
- Add isValidBucketName validation function for [a-z0-9_-] characters - Validate bucket name characters match ARN parsing regex - Fix error handling in WithFilerClient closure - properly check for lookup errors - Add error handling for json.Marshal calls (metadata and tags) - Improve error messages and logging
This commit is contained in:
@@ -24,12 +24,18 @@ func (h *S3TablesHandler) handleCreateTableBucket(w http.ResponseWriter, r *http
|
||||
return fmt.Errorf("name is required")
|
||||
}
|
||||
|
||||
// Validate bucket name
|
||||
// Validate bucket name length
|
||||
if len(req.Name) < 3 || len(req.Name) > 63 {
|
||||
h.writeError(w, http.StatusBadRequest, ErrCodeInvalidRequest, "bucket name must be between 3 and 63 characters")
|
||||
return fmt.Errorf("invalid bucket name length")
|
||||
}
|
||||
|
||||
// Validate bucket name characters [a-z0-9_-]
|
||||
if !isValidBucketName(req.Name) {
|
||||
h.writeError(w, http.StatusBadRequest, ErrCodeInvalidRequest, "bucket name must contain only lowercase letters, numbers, hyphens, and underscores")
|
||||
return fmt.Errorf("invalid bucket name characters")
|
||||
}
|
||||
|
||||
bucketPath := getTableBucketPath(req.Name)
|
||||
|
||||
// Check if bucket already exists
|
||||
@@ -39,12 +45,22 @@ func (h *S3TablesHandler) handleCreateTableBucket(w http.ResponseWriter, r *http
|
||||
Directory: TablesPath,
|
||||
Name: req.Name,
|
||||
})
|
||||
if err == nil && resp.Entry != nil {
|
||||
if err != nil {
|
||||
// Not found is expected when creating a new bucket
|
||||
return nil
|
||||
}
|
||||
if resp.Entry != nil {
|
||||
exists = true
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
glog.Errorf("S3Tables: failed to check bucket existence: %v", err)
|
||||
h.writeError(w, http.StatusInternalServerError, ErrCodeInternalError, "failed to check bucket existence")
|
||||
return err
|
||||
}
|
||||
|
||||
if exists {
|
||||
h.writeError(w, http.StatusConflict, ErrCodeBucketAlreadyExists, fmt.Sprintf("table bucket %s already exists", req.Name))
|
||||
return fmt.Errorf("bucket already exists")
|
||||
@@ -58,7 +74,12 @@ func (h *S3TablesHandler) handleCreateTableBucket(w http.ResponseWriter, r *http
|
||||
OwnerID: h.accountID,
|
||||
}
|
||||
|
||||
metadataBytes, _ := json.Marshal(metadata)
|
||||
metadataBytes, err := json.Marshal(metadata)
|
||||
if err != nil {
|
||||
glog.Errorf("S3Tables: failed to marshal metadata: %v", err)
|
||||
h.writeError(w, http.StatusInternalServerError, ErrCodeInternalError, "failed to marshal metadata")
|
||||
return err
|
||||
}
|
||||
|
||||
err = filerClient.WithFilerClient(false, func(client filer_pb.SeaweedFilerClient) error {
|
||||
// Create bucket directory
|
||||
@@ -73,7 +94,10 @@ func (h *S3TablesHandler) handleCreateTableBucket(w http.ResponseWriter, r *http
|
||||
|
||||
// Set tags if provided
|
||||
if len(req.Tags) > 0 {
|
||||
tagsBytes, _ := json.Marshal(req.Tags)
|
||||
tagsBytes, err := json.Marshal(req.Tags)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal tags: %w", err)
|
||||
}
|
||||
if err := h.setExtendedAttribute(client, bucketPath, ExtendedKeyTags, tagsBytes); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -78,6 +78,13 @@ type tableMetadataInternal struct {
|
||||
|
||||
// Utility functions
|
||||
|
||||
// isValidBucketName validates bucket name characters
|
||||
// Bucket names must contain only lowercase letters, numbers, hyphens, and underscores
|
||||
func isValidBucketName(name string) bool {
|
||||
pattern := regexp.MustCompile(`^[a-z0-9_-]+$`)
|
||||
return pattern.MatchString(name)
|
||||
}
|
||||
|
||||
// generateVersionToken generates a unique version token
|
||||
func generateVersionToken() string {
|
||||
return fmt.Sprintf("%d", time.Now().UnixNano())
|
||||
|
||||
Reference in New Issue
Block a user