Enhance server configuration for large file uploads and improve token handling. Increase request body size limit in the server to 20 GB, update registration token expiration logic to support infinite expiration, and adjust database schema to accommodate larger file sizes. Add detailed logging for file upload processes and error handling improvements.
This commit is contained in:
@@ -25,8 +25,13 @@ func (s *Server) handleGenerateRegistrationToken(w http.ResponseWriter, r *http.
|
||||
ExpiresInHours int `json:"expires_in_hours,omitempty"`
|
||||
}
|
||||
if r.Body != nil && r.ContentLength > 0 {
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err == nil && req.ExpiresInHours > 0 {
|
||||
expiresIn = time.Duration(req.ExpiresInHours) * time.Hour
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err == nil {
|
||||
if req.ExpiresInHours == 0 {
|
||||
// 0 hours means infinite expiration
|
||||
expiresIn = 0
|
||||
} else if req.ExpiresInHours > 0 {
|
||||
expiresIn = time.Duration(req.ExpiresInHours) * time.Hour
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,11 +41,17 @@ func (s *Server) handleGenerateRegistrationToken(w http.ResponseWriter, r *http.
|
||||
return
|
||||
}
|
||||
|
||||
s.respondJSON(w, http.StatusCreated, map[string]interface{}{
|
||||
"token": token,
|
||||
"expires_in": expiresIn.String(),
|
||||
"expires_at": time.Now().Add(expiresIn),
|
||||
})
|
||||
response := map[string]interface{}{
|
||||
"token": token,
|
||||
}
|
||||
if expiresIn == 0 {
|
||||
response["expires_in"] = "infinite"
|
||||
response["expires_at"] = nil
|
||||
} else {
|
||||
response["expires_in"] = expiresIn.String()
|
||||
response["expires_at"] = time.Now().Add(expiresIn)
|
||||
}
|
||||
s.respondJSON(w, http.StatusCreated, response)
|
||||
}
|
||||
|
||||
// handleListRegistrationTokens lists all registration tokens
|
||||
|
||||
@@ -841,20 +841,25 @@ func (s *Server) handleUploadJobFile(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// Parse multipart form
|
||||
err = r.ParseMultipartForm(500 << 20) // 500 MB (larger for ZIP files)
|
||||
// Parse multipart form with large limit for big files
|
||||
// Note: For very large files, this will use temporary files on disk
|
||||
err = r.ParseMultipartForm(20 << 30) // 20 GB (for large ZIP files and blend files)
|
||||
if err != nil {
|
||||
s.respondError(w, http.StatusBadRequest, "Failed to parse form")
|
||||
log.Printf("Error parsing multipart form for job %d: %v", jobID, err)
|
||||
s.respondError(w, http.StatusBadRequest, fmt.Sprintf("Failed to parse form: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
file, header, err := r.FormFile("file")
|
||||
if err != nil {
|
||||
s.respondError(w, http.StatusBadRequest, "No file provided")
|
||||
log.Printf("Error getting file from form for job %d: %v", jobID, err)
|
||||
s.respondError(w, http.StatusBadRequest, fmt.Sprintf("No file provided: %v", err))
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
log.Printf("Uploading file '%s' (size: %d bytes) for job %d", header.Filename, header.Size, jobID)
|
||||
|
||||
jobPath := s.storage.JobPath(jobID)
|
||||
if err := os.MkdirAll(jobPath, 0755); err != nil {
|
||||
s.respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to create job directory: %v", err))
|
||||
@@ -867,22 +872,34 @@ func (s *Server) handleUploadJobFile(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// Check if this is a ZIP file
|
||||
if strings.HasSuffix(strings.ToLower(header.Filename), ".zip") {
|
||||
log.Printf("Processing ZIP file '%s' for job %d", header.Filename, jobID)
|
||||
// Extract ZIP file
|
||||
zipPath := filepath.Join(jobPath, header.Filename)
|
||||
log.Printf("Creating ZIP file at: %s", zipPath)
|
||||
zipFile, err := os.Create(zipPath)
|
||||
if err != nil {
|
||||
log.Printf("ERROR: Failed to create ZIP file for job %d: %v", jobID, err)
|
||||
s.respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to create ZIP file: %v", err))
|
||||
return
|
||||
}
|
||||
_, err = io.Copy(zipFile, file)
|
||||
log.Printf("Copying %d bytes to ZIP file for job %d...", header.Size, jobID)
|
||||
copied, err := io.Copy(zipFile, file)
|
||||
zipFile.Close()
|
||||
if err != nil {
|
||||
log.Printf("ERROR: Failed to save ZIP file for job %d (copied %d bytes): %v", jobID, copied, err)
|
||||
s.respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to save ZIP file: %v", err))
|
||||
return
|
||||
}
|
||||
log.Printf("Successfully copied %d bytes to ZIP file for job %d", copied, jobID)
|
||||
|
||||
// Record ZIP file in database
|
||||
zipInfo, _ := os.Stat(zipPath)
|
||||
zipInfo, err := os.Stat(zipPath)
|
||||
if err != nil {
|
||||
log.Printf("ERROR: Failed to stat ZIP file for job %d: %v", jobID, err)
|
||||
s.respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to stat ZIP file: %v", err))
|
||||
return
|
||||
}
|
||||
log.Printf("Recording ZIP file in database for job %d (size: %d bytes)", jobID, zipInfo.Size())
|
||||
err = s.db.QueryRow(
|
||||
`INSERT INTO job_files (job_id, file_type, file_path, file_name, file_size)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
@@ -890,16 +907,21 @@ func (s *Server) handleUploadJobFile(w http.ResponseWriter, r *http.Request) {
|
||||
jobID, types.JobFileTypeInput, zipPath, header.Filename, zipInfo.Size(),
|
||||
).Scan(&fileID)
|
||||
if err != nil {
|
||||
log.Printf("ERROR: Failed to record ZIP file in database for job %d: %v", jobID, err)
|
||||
s.respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to record ZIP file: %v", err))
|
||||
return
|
||||
}
|
||||
log.Printf("ZIP file recorded in database with ID %d for job %d", fileID, jobID)
|
||||
|
||||
// Extract ZIP file
|
||||
log.Printf("Extracting ZIP file for job %d...", jobID)
|
||||
extractedFiles, err = s.storage.ExtractZip(zipPath, jobPath)
|
||||
if err != nil {
|
||||
log.Printf("ERROR: Failed to extract ZIP file for job %d: %v", jobID, err)
|
||||
s.respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to extract ZIP file: %v", err))
|
||||
return
|
||||
}
|
||||
log.Printf("Successfully extracted %d files from ZIP for job %d", len(extractedFiles), jobID)
|
||||
|
||||
// Find main blend file (check for user selection first, then auto-detect)
|
||||
mainBlendParam := r.FormValue("main_blend_file")
|
||||
|
||||
@@ -70,6 +70,9 @@ func (s *Server) runnerAuthMiddleware(next http.HandlerFunc) http.HandlerFunc {
|
||||
}
|
||||
|
||||
// handleRegisterRunner registers a new runner
|
||||
// Note: Token expiration only affects whether the token can be used for registration.
|
||||
// Once a runner is registered, it receives its own runner_secret and manager_secret
|
||||
// and operates independently. The token expiration does not affect registered runners.
|
||||
func (s *Server) handleRegisterRunner(w http.ResponseWriter, r *http.Request) {
|
||||
var req struct {
|
||||
types.RegisterRunnerRequest
|
||||
@@ -90,7 +93,7 @@ func (s *Server) handleRegisterRunner(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// Validate registration token
|
||||
// Validate registration token (expiration only affects token usability, not registered runners)
|
||||
result, err := s.secrets.ValidateRegistrationTokenDetailed(req.RegistrationToken)
|
||||
if err != nil {
|
||||
s.respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to validate token: %v", err))
|
||||
@@ -119,7 +122,7 @@ func (s *Server) handleRegisterRunner(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// Generate runner secret
|
||||
// Generate runner secret (runner will use this for all future authentication, independent of token)
|
||||
runnerSecret, err := s.secrets.GenerateRunnerSecret()
|
||||
if err != nil {
|
||||
s.respondError(w, http.StatusInternalServerError, "Failed to generate runner secret")
|
||||
@@ -347,7 +350,7 @@ func (s *Server) handleUploadFileFromRunner(w http.ResponseWriter, r *http.Reque
|
||||
return
|
||||
}
|
||||
|
||||
err = r.ParseMultipartForm(100 << 20) // 100 MB
|
||||
err = r.ParseMultipartForm(50 << 30) // 50 GB (for large output files)
|
||||
if err != nil {
|
||||
s.respondError(w, http.StatusBadRequest, "Failed to parse form")
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user