Technical Debt Resolution: Hardcoded Localhost Removal
Overview
Successfully removed critical hardcoded "localhost" references from the codebase to enable flexible deployment configurations.
Changes Made
1. Backend Configuration (relay-server/config.py)
- Added:
ws_host: str = "localhost"to ServerSettings class - Environment variable:
ZHINENG_BRIDGE_WS_HOSTnow controls the WebSocket host that clients use to connect - Purpose: Separates server bind address (0.0.0.0) from client-facing address (configurable)
2. Server Files Updated
relay-server/chat_server.py
- Modified:
__init__method to use config defaults instead of hardcoded "localhost" - Imported: settings from config module
- Changed: Default values to None, then fallback to settings.server.host/port
- Updated: main() function to use ChatRelayServer() without hardcoded parameters
relay-server/server.py:177
- Modified: Host display logic to use
settings.server.ws_hostinstead of hardcoded "localhost" - Purpose: Improves logging to show the actual client-facing hostname
relay-server/health_check.py:390-395
- Modified: Print statements to use
settings.server.ws_hostinstead of hardcoded "localhost" - Impact: Health check server now displays correct URLs in startup messages
3. Frontend Configuration
web/ui/index.html
- Added: Configuration script block before bundled JavaScript
- Created:
window.ZHINENG_BRIDGE_CONFIGobject with default settings - Implemented: Dynamic loading of config/config.js if present
- Purpose: Allows production deployments to override defaults without code changes
web/ui/js/settings.ts
- Modified: All settings to read from
window.ZHINENG_BRIDGE_CONFIGif available - Updated: ws_host, ws_port, and other settings to use config object
- Pattern:
(typeof window !== 'undefined' && window.ZHINENG_BRIDGE_CONFIG?.WS_HOST) || 'localhost'
4. Configuration Files
web/ui/config/config.js.example (NEW)
- Created: Example configuration file showing all available settings
- Documented: Each setting with clear descriptions
- Usage: Users can copy to config.js and customize for their deployment
.gitignore
- Added:
web/ui/config/config.jsto ignore list - Purpose: Prevents committing deployment-specific configuration
.dockerignore
- Added:
web/ui/config/config.jsto ignore list - Purpose: Prevents including deployment-specific config in Docker images
Appropriate Uses of "localhost" (Not Changed)
The following "localhost" references remain unchanged as they are appropriate for their context:
- relay-server/ssl_manager.py:
common_name: str = "localhost"in generate_self_signed_cert()- Default parameter for SSL certificate generation
- Users can override with --common-name argument
-
Appropriate for local development
-
relay-server/ssl_manager.py:384:
common_name="localhost"in setup_development_certificates()- Specific to development environment setup
-
Appropriate use case
-
examples/basic_usage.py:
host: str = "localhost"in init- Example code default
- Can be overridden when creating client
- Appropriate for out-of-the-box examples
Environment Variables
New Configuration Variables
ZHINENG_BRIDGE_WS_HOST: WebSocket host address for client connections (default: localhost)ZHINENG_BRIDGE_SERVER_PORT: Server port (already existed, default: 8765)
Usage Examples
Development (default)
python3 relay-server/start_server.py
# Server binds to 0.0.0.0:8765, clients use ws://localhost:8765
Production with custom host
export ZHINENG_BRIDGE_WS_HOST=prod-server.example.com
python3 relay-server/start_server.py
# Server binds to 0.0.0.0:8765, clients use ws://prod-server.example.com:8765
Frontend configuration
// In web/ui/config/config.js
window.ZHINENG_BRIDGE_CONFIG = {
WS_HOST: 'prod-server.example.com',
WS_PORT: 8765,
// ... other settings
};
Testing
Configuration Loading Tests
✅ Default configuration loads correctly: - Server host (bind): 0.0.0.0 - Server ws_host (client): localhost - Server port: 8765
✅ Environment variable override works: - Server host (bind): 0.0.0.0 - Server ws_host (client): prod-server.example.com (overridden) - Server port: 8765
Docker Build Test
✅ Docker build completed successfully (14/14 steps) - All layers built without errors - Image: test-zhineng-bridge:latest
Benefits
- Flexibility: Deploy to different environments without code changes
- Security: No hardcoded URLs in production builds
- Maintainability: Single source of truth for configuration
- Development Experience: Works out-of-the-box with sensible defaults
- Production Ready: Easy to override for production deployments
Migration Guide
For existing deployments:
- No immediate action required: Defaults remain "localhost" for backward compatibility
- For production: Set
ZHINENG_BRIDGE_WS_HOSTenvironment variable - For web UI: Create
web/ui/config/config.jswith production settings - Update documentation: Document the new configuration options
Future Enhancements
Potential improvements for future iterations:
1. Add configuration validation to catch typos
2. Add a /config endpoint to retrieve current configuration
3. Implement hot-reload for configuration changes
4. Add configuration documentation to API docs
5. Consider using a configuration file format (YAML/TOML) for complex deployments
Files Modified
relay-server/config.py- Added ws_host settingrelay-server/server.py- Updated host display logicrelay-server/chat_server.py- Updated to use configrelay-server/health_check.py- Updated print statementsweb/ui/index.html- Added configuration scriptweb/ui/js/settings.ts- Updated to read from config object.gitignore- Added config/config.js.dockerignore- Added config/config.js
Files Created
web/ui/config/config.js.example- Example configuration file
Date: 2026-03-25 Status: Completed ✅ Next Steps: Update documentation to reflect new configuration options