Files
CGW-Quote-Builder/information/PRODUCT_FINDER_DEPLOYMENT.md
T
2026-04-11 00:04:09 -05:00

335 lines
9.5 KiB
Markdown

# /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
<Directory "/home/USERNAME/public_html/product-finder">
SetEnv APPLICATION_ROOT /product-finder
PassengerEnabled on
PassengerAppRoot /home/USERNAME/public_html/product-finder
PassengerPython /usr/bin/python3
Allow from all
Options -MultiViews
</Directory>
```
## 🚀 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.