# /product-finder Deployment Fix Guide ## 🔴 Problem The application works locally at `http://localhost:8080/` but fails on the server at `https://columbiawindows.com/product-finder/`. The redirect from `/product-finder` → `/product-finder/login` works, but then the login page or subsequent routes fail. ## ✅ Solution Applied Three critical changes were made to fix subdirectory deployment: ### 1. **Added PrefixMiddleware to app.py** This middleware tells Flask about the `/product-finder` prefix by setting `SCRIPT_NAME` in the WSGI environment: ```python class PrefixMiddleware: """Middleware to handle subdirectory deployments""" def __init__(self, app, prefix=''): self.app = app self.prefix = prefix.rstrip('/') def __call__(self, environ, start_response): if self.prefix and self.prefix != '/': path = environ.get('PATH_INFO', '') script_name = environ.get('SCRIPT_NAME', '') if not script_name.startswith(self.prefix): environ['SCRIPT_NAME'] = self.prefix + script_name if path.startswith(self.prefix): environ['PATH_INFO'] = path[len(self.prefix):] return self.app(environ, start_response) ``` This is automatically applied when `APPLICATION_ROOT` is set. ### 2. **Updated passenger_wsgi.py** Sets the `APPLICATION_ROOT` environment variable before importing the app: ```python if 'APPLICATION_ROOT' not in os.environ: os.environ['APPLICATION_ROOT'] = '/product-finder' ``` ### 3. **Updated config.py** Production configuration now defaults to `/product-finder`: ```python class ProductionConfig(Config): APPLICATION_ROOT = os.environ.get('APPLICATION_ROOT', '/product-finder') ``` Development still uses `/` for local testing. ## 📤 Files to Upload Upload these updated files to your server: 1. **`app/app.py`** - Contains PrefixMiddleware 2. **`app/passenger_wsgi.py`** - Sets APPLICATION_ROOT env var 3. **`app/config.py`** - Production defaults to /product-finder 4. **`app/.htaccess`** - Apache configuration (new file) 5. **All template files** - Already updated with url_for() and BASE_URL ## 🔧 Server Configuration ### Option A: Using .htaccess (Recommended) The `.htaccess` file is already configured for `/product-finder`. Upload it to your `app/` folder on the server. **Important:** Update these lines in `.htaccess`: ```apache PassengerAppRoot /home/USERNAME/public_html/product-finder PassengerPython /usr/bin/python3 # Update to your Python path ``` ### Option B: Apache Virtual Host Configuration If you have access to Apache config, add this to your virtual host: ```apache SetEnv APPLICATION_ROOT /product-finder PassengerEnabled on PassengerAppRoot /home/USERNAME/public_html/product-finder PassengerPython /usr/bin/python3 Allow from all Options -MultiViews ``` ## 🚀 Deployment Steps 1. **Backup Current Installation** ```bash mv product-finder product-finder.backup ``` 2. **Upload Updated Files** - Upload entire `app/` folder to server - Or just upload the 5 changed files listed above 3. **Restart Passenger** ```bash # In product-finder folder mkdir -p tmp touch tmp/restart.txt ``` 4. **Test the Application** - Go to: `https://columbiawindows.com/product-finder/` - Should redirect to: `https://columbiawindows.com/product-finder/login` - Login page should load with all CSS/JS - Login should work and redirect properly - All routes should work: `/product-finder/users`, etc. ## 🐛 Troubleshooting ### Issue: Still getting 404 on login page **Check server error logs:** ```bash tail -f ~/logs/error_log # or wherever your error logs are ``` **Verify APPLICATION_ROOT is set:** Add this test route to app.py temporarily: ```python @app.route('/debug-config') def debug_config(): return jsonify({ 'APPLICATION_ROOT': app.config.get('APPLICATION_ROOT'), 'script_root': request.script_root, 'url_root': request.url_root, 'base_url': request.base_url }) ``` Then visit: `https://columbiawindows.com/product-finder/debug-config` **Expected response:** ```json { "APPLICATION_ROOT": "/product-finder", "script_root": "/product-finder", "url_root": "https://columbiawindows.com/product-finder/", "base_url": "https://columbiawindows.com/product-finder/debug-config" } ``` ### Issue: CSS/JS files not loading **Check that routes are working:** - Visit: `https://columbiawindows.com/product-finder/css/styles.css` - Should return CSS file, not 404 **Check .htaccess MIME types:** Ensure these lines are in `.htaccess`: ```apache AddType text/css .css AddType application/javascript .js AddType application/json .json ``` ### Issue: Login works but redirects are wrong **Check redirect code in templates:** All JavaScript should use `BASE_URL`: ```javascript const BASE_URL = '{{ base_url }}'; window.location.href = BASE_URL + '/login'; ``` All Python redirects should use `url_for()`: ```python return redirect(url_for('login_page')) ``` ### Issue: Works locally, fails on server **Verify environment:** ```bash # SSH to server cd ~/public_html/product-finder python3 -c "import os; print(os.environ.get('APPLICATION_ROOT', 'NOT SET'))" ``` Should print: `/product-finder` **Check Passenger is using correct Python:** ```bash which python3 # Use this path in PassengerPython directive ``` ### Issue: Sessions not persisting **Check SECRET_KEY:** ```python # In config.py, production should have a fixed SECRET_KEY SECRET_KEY = 'your-fixed-secret-key-here' # Don't use secrets.token_hex() in production ``` **Check cookie settings:** Session cookies need to work with the subdirectory path. ### Issue: API calls return 404 **Check browser console:** Press F12, go to Network tab, and check the actual URLs being called. **Should see:** ``` https://columbiawindows.com/product-finder/api/login https://columbiawindows.com/product-finder/api/session ``` **If you see:** ``` https://columbiawindows.com/api/login ❌ Missing prefix ``` Then `BASE_URL` is not set correctly in template. ## ✅ Verification Checklist After deployment, test these in order: - [ ] Visit `https://columbiawindows.com/product-finder/` - Should redirect to `/product-finder/login` ✓ - [ ] Login page loads - CSS styled correctly ✓ - No 404s in browser console ✓ - [ ] Login with Master/Master - Should redirect to `/product-finder/select-location` ✓ - [ ] Select a location - Should redirect to `/product-finder/` ✓ - [ ] User info shows in header ✓ - [ ] Click "User Management" (if Master user) - Should go to `/product-finder/users` ✓ - [ ] Logout - Should return to `/product-finder/login` ✓ ## 📝 Key Points 1. **The middleware is critical** - It tells Flask about the `/product-finder` prefix 2. **passenger_wsgi.py sets the env var** - Before importing the app 3. **All templates use BASE_URL** - For JavaScript fetch calls 4. **All routes use url_for()** - For Python redirects 5. **Production config defaults to /product-finder** - Development stays at / ## 🔄 Rolling Back If something goes wrong: ```bash # Remove new files rm -rf product-finder # Restore backup mv product-finder.backup product-finder # Restart Passenger touch product-finder/tmp/restart.txt ``` ## 📞 Still Having Issues? Run this diagnostic script on the server: ```python # Save as test_deployment.py in product-finder folder import os import sys print("=" * 60) print("DEPLOYMENT DIAGNOSTIC") print("=" * 60) print(f"Python Version: {sys.version}") print(f"Current Directory: {os.getcwd()}") print(f"APPLICATION_ROOT env: {os.environ.get('APPLICATION_ROOT', 'NOT SET')}") print() try: os.environ['APPLICATION_ROOT'] = '/product-finder' from app import app print("✓ App imported successfully") print(f"APPLICATION_ROOT config: {app.config.get('APPLICATION_ROOT')}") print(f"Middleware applied: {'PrefixMiddleware' in str(type(app.wsgi_app))}") except Exception as e: print(f"✗ Error importing app: {e}") import traceback traceback.print_exc() ``` Run with: `python3 test_deployment.py` ## 🎯 Expected Behavior **Before these changes:** - Redirect works: `/product-finder` → `/product-finder/login` ✓ - Login page loads BUT Flask doesn't know about `/product-finder` prefix - All `url_for()` calls generate `/login` instead of `/product-finder/login` ❌ - Result: 404 errors on subpages **After these changes:** - Flask knows it's at `/product-finder` via middleware ✓ - All `url_for()` generates `/product-finder/login` ✓ - All templates use `BASE_URL = '/product-finder'` ✓ - Result: Everything works ✓ ## 🆘 Quick Fix Checklist If deployed and not working: 1. [ ] Uploaded `app/app.py` with PrefixMiddleware? 2. [ ] Uploaded `app/passenger_wsgi.py` with env var setting? 3. [ ] Uploaded `app/.htaccess` with SetEnv directive? 4. [ ] Ran `touch tmp/restart.txt` to restart Passenger? 5. [ ] Checked error logs for Python errors? 6. [ ] Tested `/product-finder/debug-config` route? 7. [ ] Verified cookies are being set (F12 > Application > Cookies)? If all checked and still failing, check server error logs for the actual Python error.