Loading start.sh +42 −314 Original line number Diff line number Diff line Loading @@ -1070,14 +1070,16 @@ else mkdir -p /tmp/mock-server cd /tmp/mock-server # Create a simple Go module setup # Create a proper Go module structure - this is critical for the build echo "==> Creating proper Go module structure" touch go.mod # Initialize an explicit Go module echo "module mock-server" > go.mod echo "go 1.19" >> go.mod # Write main.go correctly echo "==> Writing main.go for mock API server" cat > main.go << EOF # Write main.go as a single file with correct quoted heredoc echo "==> Writing main.go file for mock API server" cat > main.go <<'ENDOFPROGRAM' package main import ( Loading @@ -1092,7 +1094,6 @@ import ( "strings" "time" "regexp" "encoding/base64" ) func main() { Loading Loading @@ -1139,291 +1140,6 @@ func main() { fmt.Fprintf(w, `{"status":"ok","version":"mock-1.0.0","time":"%s"}`, time.Now().Format(time.RFC3339)) }) // Handle OTT (One-Time Token) requests - this is the SPECIFIC endpoint the Ente client uses http.HandleFunc("/users/ott", func(w http.ResponseWriter, r *http.Request) { if r.Method == "POST" { body, err := io.ReadAll(r.Body) if err != nil { http.Error(w, "Error reading request body", http.StatusBadRequest) return } logger.Printf("REGISTRATION REQUEST TO /users/ott: %s", string(body)) // Extract email from request - simplified parsing emailStart := strings.Index(string(body), "\"email\":\"") var email string if emailStart >= 0 { emailStart += 9 // Length of "\"email\":\"" emailEnd := strings.Index(string(body)[emailStart:], "\"") if emailEnd >= 0 { email = string(body)[emailStart : emailStart+emailEnd] } } // Generate verification code - 6 digits for OTT verificationCode := fmt.Sprintf("%06d", 100000 + rand.Intn(900000)) // 6-digit code if email != "" { verificationCodes[email] = verificationCode logger.Printf("===================================================") logger.Printf("⚠️ OTT/VERIFICATION CODE for %s: %s", email, verificationCode) logger.Printf("===================================================") // Also log to console for immediate visibility fmt.Printf("===================================================\n") fmt.Printf("⚠️ OTT/VERIFICATION CODE for %s: %s\n", email, verificationCode) fmt.Printf("===================================================\n") } // Return a success response with properly formatted data w.Header().Set("Content-Type", "application/json") // Create a response with the required fields jsonResponse := map[string]interface{}{ "status": "ok", "id": 12345, // Add required ID field as a number "token": "mock-token-12345", "ott": verificationCode, "exp": time.Now().Add(time.Hour).Unix(), "email": email, "createdAt": time.Now().Format(time.RFC3339), "updatedAt": time.Now().Format(time.RFC3339), "key": map[string]interface{}{ "pubKey": "mockPubKey123456", "encPubKey": "mockEncPubKey123456", "kty": "mockKty", "kid": "mockKid", "alg": "mockAlg", "verifyKey": "mockVerifyKey123456", }, } json.NewEncoder(w).Encode(jsonResponse) } else { // Just handle other methods with a generic response w.Header().Set("Content-Type", "application/json") fmt.Fprintf(w, `{"status":"mock","endpoint":"%s","method":"%s"}`, r.URL.Path, r.Method) } }) // Handle registration requests http.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) { if r.Method == "POST" { body, err := io.ReadAll(r.Body) if err != nil { http.Error(w, "Error reading request body", http.StatusBadRequest) return } logger.Printf("REGISTRATION REQUEST TO /users: %s", string(body)) // Extract email from request - simplified parsing emailStart := strings.Index(string(body), "\"email\":\"") var email string if emailStart >= 0 { emailStart += 9 // Length of "\"email\":\"" emailEnd := strings.Index(string(body)[emailStart:], "\"") if emailEnd >= 0 { email = string(body)[emailStart : emailStart+emailEnd] } } // Generate verification code verificationCode := strconv.Itoa(100000 + rand.Intn(900000)) // 6-digit code if email != "" { verificationCodes[email] = verificationCode logger.Printf("===================================================") logger.Printf("⚠️ VERIFICATION CODE for %s: %s", email, verificationCode) logger.Printf("===================================================") // Also log to console for immediate visibility fmt.Printf("===================================================\n") fmt.Printf("⚠️ VERIFICATION CODE for %s: %s\n", email, verificationCode) fmt.Printf("===================================================\n") } // Return a success response w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) // Use the encoding/json package to create and send the response jsonResponse := map[string]string{ "status": "ok", "message": "Verification code sent (check logs)", } json.NewEncoder(w).Encode(jsonResponse) } else { // Just handle other methods with a generic response w.Header().Set("Content-Type", "application/json") fmt.Fprintf(w, `{"status":"mock","endpoint":"%s","method":"%s"}`, r.URL.Path, r.Method) } }) // Handle verification endpoint http.HandleFunc("/users/verification", func(w http.ResponseWriter, r *http.Request) { if r.Method == "POST" { body, err := io.ReadAll(r.Body) if err != nil { http.Error(w, "Error reading request body", http.StatusBadRequest) return } logger.Printf("VERIFICATION REQUEST: %s", string(body)) // Extract email and code using more robust parsing var email, code string // Extract email from JSON emailStart := strings.Index(string(body), "\"email\":\"") if emailStart >= 0 { emailStart += 9 emailEnd := strings.Index(string(body)[emailStart:], "\"") if emailEnd >= 0 { email = string(body)[emailStart : emailStart+emailEnd] } } // Try to extract code from various possible JSON formats // First try string format: "code":"123456" codeStart := strings.Index(string(body), "\"code\":\"") if codeStart >= 0 { codeStart += 8 codeEnd := strings.Index(string(body)[codeStart:], "\"") if codeEnd >= 0 { code = string(body)[codeStart : codeStart+codeEnd] } } // If not found, try numeric format: "code":123456 if code == "" { codeStart = strings.Index(string(body), "\"code\":") if codeStart >= 0 && !strings.Contains(string(body)[codeStart:codeStart+10], "\"") { codeStart += 7 codeEnd := strings.IndexAny(string(body)[codeStart:], ",}") if codeEnd >= 0 { code = strings.TrimSpace(string(body)[codeStart : codeStart+codeEnd]) } } } // Look for ott in string format: "ott":"123456" if code == "" { ottStart := strings.Index(string(body), "\"ott\":\"") if ottStart >= 0 { ottStart += 7 ottEnd := strings.Index(string(body)[ottStart:], "\"") if ottEnd >= 0 { code = string(body)[ottStart : ottStart+ottEnd] } } } // Look for ott in numeric format: "ott":123456 if code == "" { ottStart := strings.Index(string(body), "\"ott\":") if ottStart >= 0 && !strings.Contains(string(body)[ottStart:ottStart+10], "\"") { ottStart += 6 ottEnd := strings.IndexAny(string(body)[ottStart:], ",}") if ottEnd >= 0 { code = strings.TrimSpace(string(body)[ottStart : ottStart+ottEnd]) } } } // Last resort: search for a 6-digit number anywhere in the request if code == "" { r := regexp.MustCompile("\\b\\d{6}\\b") matches := r.FindStringSubmatch(string(body)) if len(matches) > 0 { code = matches[0] logger.Printf("Found 6-digit code using regex: %s", code) } } logger.Printf("Extracted email: '%s', code: '%s' from verification request", email, code) // Verify the code isValid := false if email != "" && code != "" { expectedCode, exists := verificationCodes[email] logger.Printf("VerificationCodes map: %v", verificationCodes) logger.Printf("Verifying code %s for email %s (expected: %s, exists: %v)", code, email, expectedCode, exists) if !exists && email == "" { logger.Printf("ERROR: Incomplete verification request - missing email and/or no code was requested previously") w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusBadRequest) fmt.Fprintf(w, `{"error": "Verification code not found or expired"}`) return } // Accept if: // 1. It matches the expected code, or // 2. It's "123456" (our special test code), or // 3. It's any valid 6-digit code (for easier testing) validSixDigitCode := len(code) == 6 && regexp.MustCompile(`^\d{6}$`).MatchString(code) if (exists && code == expectedCode) || code == "123456" || validSixDigitCode { isValid = true logger.Printf("✅ SUCCESS: Code verified successfully for email: %s (expected: %s, provided: %s)", email, expectedCode, code) // Clear the verification code after successful verification delete(verificationCodes, email) } else { logger.Printf("❌ ERROR: Invalid verification code for email: %s (expected: %s, provided: %s)", email, expectedCode, code) } } else { logger.Printf("❌ INCOMPLETE VERIFICATION REQUEST - email: '%s', code: '%s'", email, code) fmt.Printf("❌ INCOMPLETE VERIFICATION REQUEST - email: '%s', code: '%s'\n", email, code) } w.Header().Set("Content-Type", "application/json") if isValid { // Return a successful verification response with required fields w.WriteHeader(http.StatusOK) // Use the json package to create the response with all fields expected by client jsonResponse := map[string]interface{}{ "status": "ok", "id": 12345, // Add required numeric ID "token": "mock-token-12345", "email": email, "createdAt": time.Now().Unix() - 3600, "updatedAt": time.Now().Unix(), "key": map[string]interface{}{ "pubKey": "mockPubKey123456", "encPubKey": "mockEncPubKey123456", "kty": "mockKty", "kid": "mockKid", "alg": "mockAlg", "verifyKey": "mockVerifyKey123456", }, "isEmailVerified": true, "twoFactorAuth": false, "recoveryKey": map[string]interface{}{ "isSet": false, }, "displayName": email, "isRevoked": false, } json.NewEncoder(w).Encode(jsonResponse) } else { // Return an error w.WriteHeader(http.StatusBadRequest) // Use the json package to create the error response jsonResponse := map[string]string{ "status": "error", "message": "Invalid verification code", } json.NewEncoder(w).Encode(jsonResponse) } } else { // Handle other methods with a generic response w.Header().Set("Content-Type", "application/json") fmt.Fprintf(w, `{"status":"mock","endpoint":"%s","method":"%s"}`, r.URL.Path, r.Method) } }) // Generic handler for all other requests http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { logger.Printf("Received request for %s via %s", r.URL.Path, r.Method) Loading Loading @@ -1456,32 +1172,40 @@ func main() { logger.Fatalf("Server failed: %v", err) } } EOF ENDOFPROGRAM # Show the created files for debugging echo "==> Listing created files:" ls -la echo "==> Contents of go.mod:" cat go.mod # Completely unset Go module-related environment variables # Completely unset Go module environment variables echo "==> Unsetting module flags before building mock server" unset GO111MODULE unset GOFLAGS unset GOMODCACHE unset GOPATH unset GOMODCACHE # Show directory content for debugging echo "==> Current directory contents:" ls -la # Build the mock server using the direct build command echo "==> Building mock API server on port 8080" # Build and run the mock server in the background echo "==> Building and starting mock API server on port 8080" # Show Go version go version # Build without specifying the file (shorter command) if go build -v .; then # Set SERVER_PID to 0 initially - CRITICAL for avoiding unbound variable later SERVER_PID=0 # Try building with explicit output file if go build -o mock_server .; then echo "==> Successfully compiled mock API server" # Create log directory if it doesn't exist mkdir -p /app/data/logs # Start the server and log both to file and to console chmod +x ./mock-server nohup ./mock-server > /app/data/logs/mock_server.log 2>&1 & chmod +x ./mock_server nohup ./mock_server > /app/data/logs/mock_server.log 2>&1 & SERVER_PID=$! echo "==> Mock API server started with PID $SERVER_PID" Loading @@ -1505,17 +1229,13 @@ EOF echo "==> ERROR: Mock API server failed to start" echo "==> Server log:" cat /app/data/logs/mock_server.log # Reset SERVER_PID if process died SERVER_PID=0 fi else echo "==> ERROR: Failed to build mock API server" # Print Go version and current directory for debugging go version pwd ls -la echo "==> Current directory content:" cat main.go | head -10 # Set a fallback value for SERVER_PID SERVER_PID=0 # Server PID is already set to 0 above fi fi Loading Loading @@ -2236,7 +1956,15 @@ EOF # Trap to kill the tail process when the script exits trap 'kill -TERM $TAIL_PID; kill -TERM $SERVER_PID; kill -TERM $PUBLIC_SERVER_PID; kill -TERM $CADDY_PID; exit' TERM INT # Wait for all processes wait $SERVER_PID wait $PUBLIC_SERVER_PID wait $CADDY_PID No newline at end of file # Wait for all processes - only if they exist/are set if [ -n "${SERVER_PID:-}" ] && [ "${SERVER_PID:-0}" -ne 0 ]; then wait $SERVER_PID || true fi if [ -n "${PUBLIC_SERVER_PID:-}" ] && [ "${PUBLIC_SERVER_PID:-0}" -ne 0 ]; then wait $PUBLIC_SERVER_PID || true fi if [ -n "${CADDY_PID:-}" ] && [ "${CADDY_PID:-0}" -ne 0 ]; then wait $CADDY_PID || true fi No newline at end of file Loading
start.sh +42 −314 Original line number Diff line number Diff line Loading @@ -1070,14 +1070,16 @@ else mkdir -p /tmp/mock-server cd /tmp/mock-server # Create a simple Go module setup # Create a proper Go module structure - this is critical for the build echo "==> Creating proper Go module structure" touch go.mod # Initialize an explicit Go module echo "module mock-server" > go.mod echo "go 1.19" >> go.mod # Write main.go correctly echo "==> Writing main.go for mock API server" cat > main.go << EOF # Write main.go as a single file with correct quoted heredoc echo "==> Writing main.go file for mock API server" cat > main.go <<'ENDOFPROGRAM' package main import ( Loading @@ -1092,7 +1094,6 @@ import ( "strings" "time" "regexp" "encoding/base64" ) func main() { Loading Loading @@ -1139,291 +1140,6 @@ func main() { fmt.Fprintf(w, `{"status":"ok","version":"mock-1.0.0","time":"%s"}`, time.Now().Format(time.RFC3339)) }) // Handle OTT (One-Time Token) requests - this is the SPECIFIC endpoint the Ente client uses http.HandleFunc("/users/ott", func(w http.ResponseWriter, r *http.Request) { if r.Method == "POST" { body, err := io.ReadAll(r.Body) if err != nil { http.Error(w, "Error reading request body", http.StatusBadRequest) return } logger.Printf("REGISTRATION REQUEST TO /users/ott: %s", string(body)) // Extract email from request - simplified parsing emailStart := strings.Index(string(body), "\"email\":\"") var email string if emailStart >= 0 { emailStart += 9 // Length of "\"email\":\"" emailEnd := strings.Index(string(body)[emailStart:], "\"") if emailEnd >= 0 { email = string(body)[emailStart : emailStart+emailEnd] } } // Generate verification code - 6 digits for OTT verificationCode := fmt.Sprintf("%06d", 100000 + rand.Intn(900000)) // 6-digit code if email != "" { verificationCodes[email] = verificationCode logger.Printf("===================================================") logger.Printf("⚠️ OTT/VERIFICATION CODE for %s: %s", email, verificationCode) logger.Printf("===================================================") // Also log to console for immediate visibility fmt.Printf("===================================================\n") fmt.Printf("⚠️ OTT/VERIFICATION CODE for %s: %s\n", email, verificationCode) fmt.Printf("===================================================\n") } // Return a success response with properly formatted data w.Header().Set("Content-Type", "application/json") // Create a response with the required fields jsonResponse := map[string]interface{}{ "status": "ok", "id": 12345, // Add required ID field as a number "token": "mock-token-12345", "ott": verificationCode, "exp": time.Now().Add(time.Hour).Unix(), "email": email, "createdAt": time.Now().Format(time.RFC3339), "updatedAt": time.Now().Format(time.RFC3339), "key": map[string]interface{}{ "pubKey": "mockPubKey123456", "encPubKey": "mockEncPubKey123456", "kty": "mockKty", "kid": "mockKid", "alg": "mockAlg", "verifyKey": "mockVerifyKey123456", }, } json.NewEncoder(w).Encode(jsonResponse) } else { // Just handle other methods with a generic response w.Header().Set("Content-Type", "application/json") fmt.Fprintf(w, `{"status":"mock","endpoint":"%s","method":"%s"}`, r.URL.Path, r.Method) } }) // Handle registration requests http.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) { if r.Method == "POST" { body, err := io.ReadAll(r.Body) if err != nil { http.Error(w, "Error reading request body", http.StatusBadRequest) return } logger.Printf("REGISTRATION REQUEST TO /users: %s", string(body)) // Extract email from request - simplified parsing emailStart := strings.Index(string(body), "\"email\":\"") var email string if emailStart >= 0 { emailStart += 9 // Length of "\"email\":\"" emailEnd := strings.Index(string(body)[emailStart:], "\"") if emailEnd >= 0 { email = string(body)[emailStart : emailStart+emailEnd] } } // Generate verification code verificationCode := strconv.Itoa(100000 + rand.Intn(900000)) // 6-digit code if email != "" { verificationCodes[email] = verificationCode logger.Printf("===================================================") logger.Printf("⚠️ VERIFICATION CODE for %s: %s", email, verificationCode) logger.Printf("===================================================") // Also log to console for immediate visibility fmt.Printf("===================================================\n") fmt.Printf("⚠️ VERIFICATION CODE for %s: %s\n", email, verificationCode) fmt.Printf("===================================================\n") } // Return a success response w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) // Use the encoding/json package to create and send the response jsonResponse := map[string]string{ "status": "ok", "message": "Verification code sent (check logs)", } json.NewEncoder(w).Encode(jsonResponse) } else { // Just handle other methods with a generic response w.Header().Set("Content-Type", "application/json") fmt.Fprintf(w, `{"status":"mock","endpoint":"%s","method":"%s"}`, r.URL.Path, r.Method) } }) // Handle verification endpoint http.HandleFunc("/users/verification", func(w http.ResponseWriter, r *http.Request) { if r.Method == "POST" { body, err := io.ReadAll(r.Body) if err != nil { http.Error(w, "Error reading request body", http.StatusBadRequest) return } logger.Printf("VERIFICATION REQUEST: %s", string(body)) // Extract email and code using more robust parsing var email, code string // Extract email from JSON emailStart := strings.Index(string(body), "\"email\":\"") if emailStart >= 0 { emailStart += 9 emailEnd := strings.Index(string(body)[emailStart:], "\"") if emailEnd >= 0 { email = string(body)[emailStart : emailStart+emailEnd] } } // Try to extract code from various possible JSON formats // First try string format: "code":"123456" codeStart := strings.Index(string(body), "\"code\":\"") if codeStart >= 0 { codeStart += 8 codeEnd := strings.Index(string(body)[codeStart:], "\"") if codeEnd >= 0 { code = string(body)[codeStart : codeStart+codeEnd] } } // If not found, try numeric format: "code":123456 if code == "" { codeStart = strings.Index(string(body), "\"code\":") if codeStart >= 0 && !strings.Contains(string(body)[codeStart:codeStart+10], "\"") { codeStart += 7 codeEnd := strings.IndexAny(string(body)[codeStart:], ",}") if codeEnd >= 0 { code = strings.TrimSpace(string(body)[codeStart : codeStart+codeEnd]) } } } // Look for ott in string format: "ott":"123456" if code == "" { ottStart := strings.Index(string(body), "\"ott\":\"") if ottStart >= 0 { ottStart += 7 ottEnd := strings.Index(string(body)[ottStart:], "\"") if ottEnd >= 0 { code = string(body)[ottStart : ottStart+ottEnd] } } } // Look for ott in numeric format: "ott":123456 if code == "" { ottStart := strings.Index(string(body), "\"ott\":") if ottStart >= 0 && !strings.Contains(string(body)[ottStart:ottStart+10], "\"") { ottStart += 6 ottEnd := strings.IndexAny(string(body)[ottStart:], ",}") if ottEnd >= 0 { code = strings.TrimSpace(string(body)[ottStart : ottStart+ottEnd]) } } } // Last resort: search for a 6-digit number anywhere in the request if code == "" { r := regexp.MustCompile("\\b\\d{6}\\b") matches := r.FindStringSubmatch(string(body)) if len(matches) > 0 { code = matches[0] logger.Printf("Found 6-digit code using regex: %s", code) } } logger.Printf("Extracted email: '%s', code: '%s' from verification request", email, code) // Verify the code isValid := false if email != "" && code != "" { expectedCode, exists := verificationCodes[email] logger.Printf("VerificationCodes map: %v", verificationCodes) logger.Printf("Verifying code %s for email %s (expected: %s, exists: %v)", code, email, expectedCode, exists) if !exists && email == "" { logger.Printf("ERROR: Incomplete verification request - missing email and/or no code was requested previously") w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusBadRequest) fmt.Fprintf(w, `{"error": "Verification code not found or expired"}`) return } // Accept if: // 1. It matches the expected code, or // 2. It's "123456" (our special test code), or // 3. It's any valid 6-digit code (for easier testing) validSixDigitCode := len(code) == 6 && regexp.MustCompile(`^\d{6}$`).MatchString(code) if (exists && code == expectedCode) || code == "123456" || validSixDigitCode { isValid = true logger.Printf("✅ SUCCESS: Code verified successfully for email: %s (expected: %s, provided: %s)", email, expectedCode, code) // Clear the verification code after successful verification delete(verificationCodes, email) } else { logger.Printf("❌ ERROR: Invalid verification code for email: %s (expected: %s, provided: %s)", email, expectedCode, code) } } else { logger.Printf("❌ INCOMPLETE VERIFICATION REQUEST - email: '%s', code: '%s'", email, code) fmt.Printf("❌ INCOMPLETE VERIFICATION REQUEST - email: '%s', code: '%s'\n", email, code) } w.Header().Set("Content-Type", "application/json") if isValid { // Return a successful verification response with required fields w.WriteHeader(http.StatusOK) // Use the json package to create the response with all fields expected by client jsonResponse := map[string]interface{}{ "status": "ok", "id": 12345, // Add required numeric ID "token": "mock-token-12345", "email": email, "createdAt": time.Now().Unix() - 3600, "updatedAt": time.Now().Unix(), "key": map[string]interface{}{ "pubKey": "mockPubKey123456", "encPubKey": "mockEncPubKey123456", "kty": "mockKty", "kid": "mockKid", "alg": "mockAlg", "verifyKey": "mockVerifyKey123456", }, "isEmailVerified": true, "twoFactorAuth": false, "recoveryKey": map[string]interface{}{ "isSet": false, }, "displayName": email, "isRevoked": false, } json.NewEncoder(w).Encode(jsonResponse) } else { // Return an error w.WriteHeader(http.StatusBadRequest) // Use the json package to create the error response jsonResponse := map[string]string{ "status": "error", "message": "Invalid verification code", } json.NewEncoder(w).Encode(jsonResponse) } } else { // Handle other methods with a generic response w.Header().Set("Content-Type", "application/json") fmt.Fprintf(w, `{"status":"mock","endpoint":"%s","method":"%s"}`, r.URL.Path, r.Method) } }) // Generic handler for all other requests http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { logger.Printf("Received request for %s via %s", r.URL.Path, r.Method) Loading Loading @@ -1456,32 +1172,40 @@ func main() { logger.Fatalf("Server failed: %v", err) } } EOF ENDOFPROGRAM # Show the created files for debugging echo "==> Listing created files:" ls -la echo "==> Contents of go.mod:" cat go.mod # Completely unset Go module-related environment variables # Completely unset Go module environment variables echo "==> Unsetting module flags before building mock server" unset GO111MODULE unset GOFLAGS unset GOMODCACHE unset GOPATH unset GOMODCACHE # Show directory content for debugging echo "==> Current directory contents:" ls -la # Build the mock server using the direct build command echo "==> Building mock API server on port 8080" # Build and run the mock server in the background echo "==> Building and starting mock API server on port 8080" # Show Go version go version # Build without specifying the file (shorter command) if go build -v .; then # Set SERVER_PID to 0 initially - CRITICAL for avoiding unbound variable later SERVER_PID=0 # Try building with explicit output file if go build -o mock_server .; then echo "==> Successfully compiled mock API server" # Create log directory if it doesn't exist mkdir -p /app/data/logs # Start the server and log both to file and to console chmod +x ./mock-server nohup ./mock-server > /app/data/logs/mock_server.log 2>&1 & chmod +x ./mock_server nohup ./mock_server > /app/data/logs/mock_server.log 2>&1 & SERVER_PID=$! echo "==> Mock API server started with PID $SERVER_PID" Loading @@ -1505,17 +1229,13 @@ EOF echo "==> ERROR: Mock API server failed to start" echo "==> Server log:" cat /app/data/logs/mock_server.log # Reset SERVER_PID if process died SERVER_PID=0 fi else echo "==> ERROR: Failed to build mock API server" # Print Go version and current directory for debugging go version pwd ls -la echo "==> Current directory content:" cat main.go | head -10 # Set a fallback value for SERVER_PID SERVER_PID=0 # Server PID is already set to 0 above fi fi Loading Loading @@ -2236,7 +1956,15 @@ EOF # Trap to kill the tail process when the script exits trap 'kill -TERM $TAIL_PID; kill -TERM $SERVER_PID; kill -TERM $PUBLIC_SERVER_PID; kill -TERM $CADDY_PID; exit' TERM INT # Wait for all processes wait $SERVER_PID wait $PUBLIC_SERVER_PID wait $CADDY_PID No newline at end of file # Wait for all processes - only if they exist/are set if [ -n "${SERVER_PID:-}" ] && [ "${SERVER_PID:-0}" -ne 0 ]; then wait $SERVER_PID || true fi if [ -n "${PUBLIC_SERVER_PID:-}" ] && [ "${PUBLIC_SERVER_PID:-0}" -ne 0 ]; then wait $PUBLIC_SERVER_PID || true fi if [ -n "${CADDY_PID:-}" ] && [ "${CADDY_PID:-0}" -ne 0 ]; then wait $CADDY_PID || true fi No newline at end of file