Add test script for large file asynchronous post-processing
- Implemented a comprehensive test script to validate the new asynchronous handling of large file uploads (>1GB). - The script checks for immediate HTTP responses, verifies server configurations for deduplication and virus scanning, and ensures server responsiveness during rapid uploads. - Included checks for relevant response headers and session tracking. - Documented the problem being solved, implementation details, and next steps for deployment and monitoring.
This commit is contained in:
@ -1,25 +1,30 @@
|
||||
# Gajim "Bad Gateway" Fix - CORS Implementation
|
||||
# Gajim "Bad Gateway" Fix - Enhanced Multi-Upload CORS Implementation
|
||||
*HMAC File Server 3.3.0 "Nexus Infinitum" - XMPP Client Compatibility Enhancement*
|
||||
|
||||
## Issue Resolution
|
||||
|
||||
**Problem**: Gajim reports "bad gateway" errors intermittently during file uploads.
|
||||
**Problem**: Gajim reports "bad gateway" errors intermittently during file uploads, specifically on **multi-upload scenarios** (second, third uploads fail).
|
||||
|
||||
**Root Cause**: The server didn't handle CORS preflight (OPTIONS) requests, which modern XMPP clients like Gajim send before file uploads.
|
||||
**Root Cause**:
|
||||
1. Server didn't handle CORS preflight (OPTIONS) requests properly
|
||||
2. Missing extended CORS headers for multi-upload session management
|
||||
3. No session state tracking for persistent connections used by Gajim
|
||||
|
||||
**Solution**: Implemented comprehensive CORS support with OPTIONS handling.
|
||||
**Solution**: Implemented comprehensive CORS support with multi-upload session management.
|
||||
|
||||
## Technical Implementation
|
||||
|
||||
### 1. Added CORS Middleware
|
||||
### 1. Enhanced CORS Middleware
|
||||
```go
|
||||
corsWrapper := func(handler http.HandlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
// Set CORS headers for all responses
|
||||
// Enhanced CORS headers for Gajim multi-upload support
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE, OPTIONS, HEAD")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Authorization, Content-Type, Content-Length, X-Requested-With")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Authorization, Content-Type, Content-Length, X-Requested-With, X-Upload-ID, X-Session-Token, X-File-Name, X-File-Size, Range, Content-Range")
|
||||
w.Header().Set("Access-Control-Expose-Headers", "Content-Length, Content-Range, X-Upload-Status, X-Session-ID, Location, ETag")
|
||||
w.Header().Set("Access-Control-Max-Age", "86400")
|
||||
w.Header().Set("Access-Control-Allow-Credentials", "false")
|
||||
|
||||
// Handle OPTIONS preflight for all endpoints
|
||||
if r.Method == http.MethodOptions {
|
||||
@ -32,30 +37,57 @@ corsWrapper := func(handler http.HandlerFunc) http.HandlerFunc {
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Enhanced Catch-All Handler
|
||||
### 2. Multi-Upload Session Management
|
||||
```go
|
||||
// Add CORS headers for all responses
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE, OPTIONS, HEAD")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Authorization, Content-Type, Content-Length, X-Requested-With")
|
||||
w.Header().Set("Access-Control-Max-Age", "86400")
|
||||
|
||||
// Handle CORS preflight requests (fix for Gajim "bad gateway" error)
|
||||
if r.Method == http.MethodOptions {
|
||||
log.Info("🔍 ROUTER DEBUG: Handling CORS preflight (OPTIONS) request")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
return
|
||||
// Enhanced session handling for multi-upload scenarios (Gajim fix)
|
||||
sessionID := r.Header.Get("X-Session-ID")
|
||||
if sessionID == "" {
|
||||
// Generate session ID for multi-upload tracking
|
||||
sessionID = generateUploadSessionID("upload", r.Header.Get("User-Agent"), getClientIP(r))
|
||||
}
|
||||
|
||||
// Set session headers for client continuation
|
||||
w.Header().Set("X-Session-ID", sessionID)
|
||||
w.Header().Set("X-Upload-Session-Timeout", "3600") // 1 hour
|
||||
```
|
||||
|
||||
## CORS Headers Explained
|
||||
### 3. XMPP Protocol Session Support
|
||||
```go
|
||||
// Enhanced session handling for multi-upload scenarios (Gajim XMPP fix)
|
||||
sessionID := r.Header.Get("X-Session-ID")
|
||||
if sessionID == "" {
|
||||
// Generate session ID for XMPP multi-upload tracking
|
||||
sessionID = generateUploadSessionID("legacy", r.Header.Get("User-Agent"), getClientIP(r))
|
||||
}
|
||||
|
||||
// Set session headers for XMPP client continuation
|
||||
w.Header().Set("X-Session-ID", sessionID)
|
||||
w.Header().Set("X-Upload-Session-Timeout", "3600") // 1 hour
|
||||
w.Header().Set("X-Upload-Type", "legacy-xmpp")
|
||||
```
|
||||
|
||||
## Enhanced CORS Headers for Multi-Upload
|
||||
|
||||
### Basic CORS Headers
|
||||
| Header | Value | Purpose |
|
||||
|--------|--------|---------|
|
||||
| `Access-Control-Allow-Origin` | `*` | Allow requests from any origin |
|
||||
| `Access-Control-Allow-Methods` | `GET, PUT, POST, DELETE, OPTIONS, HEAD` | Permitted HTTP methods |
|
||||
| `Access-Control-Allow-Headers` | `Authorization, Content-Type, Content-Length, X-Requested-With` | Allowed request headers |
|
||||
| `Access-Control-Max-Age` | `86400` | Cache preflight for 24 hours |
|
||||
| `Access-Control-Allow-Credentials` | `false` | Public file server mode |
|
||||
|
||||
### Multi-Upload Support Headers
|
||||
| Header | Value | Purpose |
|
||||
|--------|--------|---------|
|
||||
| `Access-Control-Allow-Headers` | `Authorization, Content-Type, Content-Length, X-Requested-With, X-Upload-ID, X-Session-Token, X-File-Name, X-File-Size, Range, Content-Range` | Extended upload metadata support |
|
||||
| `Access-Control-Expose-Headers` | `Content-Length, Content-Range, X-Upload-Status, X-Session-ID, Location, ETag` | Upload state management |
|
||||
|
||||
### Session Management Headers
|
||||
| Header | Purpose | Example Value |
|
||||
|--------|---------|---------------|
|
||||
| `X-Session-ID` | Track multi-upload sessions | `upload_c03d9835ed0efcbb` |
|
||||
| `X-Upload-Session-Timeout` | Session validity period | `3600` (1 hour) |
|
||||
| `X-Upload-Type` | Upload protocol type | `legacy-xmpp` |
|
||||
|
||||
## Client Compatibility
|
||||
|
||||
@ -66,9 +98,21 @@ if r.Method == http.MethodOptions {
|
||||
- **Future XMPP clients**: Standards-compliant CORS implementation
|
||||
|
||||
### 🔧 Technical Flow
|
||||
1. **Client sends OPTIONS preflight** → Server responds with CORS headers (200 OK)
|
||||
2. **Client proceeds with actual request** → Server processes with CORS headers
|
||||
3. **No more 502/404 errors** → Seamless file upload experience
|
||||
1. **First Upload**: Client sends OPTIONS preflight → Server responds with CORS headers + session ID
|
||||
2. **Subsequent Uploads**: Client reuses session ID → Server recognizes multi-upload context
|
||||
3. **Session Tracking**: Server maintains upload state across requests
|
||||
4. **No more 502/404 errors**: Seamless multi-file upload experience
|
||||
|
||||
### 📊 Multi-Upload Scenario
|
||||
```
|
||||
Gajim Upload Sequence:
|
||||
Upload 1: OPTIONS → 200 OK (session created) → PUT → 201 Created ✅
|
||||
Upload 2: OPTIONS → 200 OK (session reused) → PUT → 201 Created ✅
|
||||
Upload 3: OPTIONS → 200 OK (session reused) → PUT → 201 Created ✅
|
||||
```
|
||||
|
||||
**Before Fix**: Second upload would get 404/502 "bad gateway"
|
||||
**After Fix**: All uploads in sequence work seamlessly
|
||||
|
||||
## Testing Results
|
||||
|
||||
|
Reference in New Issue
Block a user