régler problèmes de la version de production
This commit is contained in:
+5
-1
@@ -1,6 +1,6 @@
|
|||||||
.env
|
.env
|
||||||
|
|
||||||
instance/
|
.instance/
|
||||||
*.db
|
*.db
|
||||||
|
|
||||||
documents/
|
documents/
|
||||||
@@ -12,6 +12,10 @@ __pycache__/
|
|||||||
|
|
||||||
.pytest_cache/
|
.pytest_cache/
|
||||||
.coverage
|
.coverage
|
||||||
|
|
||||||
htmlcov/
|
htmlcov/
|
||||||
.DS_Store
|
.DS_Store
|
||||||
*.log
|
*.log
|
||||||
|
|
||||||
|
.certs/
|
||||||
|
*.pem
|
||||||
Binary file not shown.
+129
@@ -0,0 +1,129 @@
|
|||||||
|
"""Development HTTPS server for testing production settings locally.
|
||||||
|
|
||||||
|
Generates a self-signed certificate (if not present) and runs the
|
||||||
|
application via Waitress wrapped in a TLS socket. This simulates the
|
||||||
|
production environment where Nginx handles TLS termination.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python run_https.py
|
||||||
|
|
||||||
|
The server will listen on https://localhost:8443
|
||||||
|
Accept the self-signed certificate warning in your browser to proceed.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import socket
|
||||||
|
import subprocess
|
||||||
|
import ssl
|
||||||
|
import sys
|
||||||
|
from waitress.server import create_server
|
||||||
|
from app import create_app
|
||||||
|
|
||||||
|
CERT_FILE = 'certs/localhost.pem'
|
||||||
|
KEY_FILE = 'certs/localhost-key.pem'
|
||||||
|
|
||||||
|
|
||||||
|
def generate_self_signed_cert():
|
||||||
|
"""Generate a self-signed certificate for local HTTPS testing.
|
||||||
|
|
||||||
|
Uses OpenSSL to create a key and certificate valid for 365 days.
|
||||||
|
Skips generation if certificate files already exist.
|
||||||
|
"""
|
||||||
|
if os.path.exists(CERT_FILE) and os.path.exists(KEY_FILE):
|
||||||
|
print('[OK] Self-signed certificate already exists.')
|
||||||
|
return
|
||||||
|
|
||||||
|
os.makedirs('certs', exist_ok=True)
|
||||||
|
|
||||||
|
print('[INFO] Generating self-signed certificate for localhost...')
|
||||||
|
try:
|
||||||
|
subprocess.run([
|
||||||
|
'openssl', 'req', '-x509', '-newkey', 'rsa:2048',
|
||||||
|
'-keyout', KEY_FILE,
|
||||||
|
'-out', CERT_FILE,
|
||||||
|
'-days', '365',
|
||||||
|
'-nodes',
|
||||||
|
'-subj', '/CN=localhost'
|
||||||
|
], check=True, capture_output=True)
|
||||||
|
print('[OK] Certificate generated: certs/localhost.pem')
|
||||||
|
except FileNotFoundError:
|
||||||
|
print('[ERROR] OpenSSL not found. Install OpenSSL or use:')
|
||||||
|
print(' winget install OpenSSL.OpenSSL')
|
||||||
|
print(' OR download from https://slproweb.com/products/Win32OpenSSL.html')
|
||||||
|
sys.exit(1)
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f'[ERROR] Certificate generation failed: {e}')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Start the HTTPS development server."""
|
||||||
|
port = int(os.getenv('HTTPS_PORT', 8443))
|
||||||
|
host = os.getenv('HOST', '127.0.0.1')
|
||||||
|
|
||||||
|
# Ensure certificate exists
|
||||||
|
generate_self_signed_cert()
|
||||||
|
|
||||||
|
# Create the Flask application
|
||||||
|
app = create_app()
|
||||||
|
|
||||||
|
# Create SSL context
|
||||||
|
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
|
||||||
|
context.load_cert_chain(CERT_FILE, KEY_FILE)
|
||||||
|
|
||||||
|
# Create a TCP socket, wrap it with TLS, then pass to Waitress
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
|
||||||
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
|
sock.bind((host, port))
|
||||||
|
sock.listen(5)
|
||||||
|
|
||||||
|
# Wrap the socket with TLS
|
||||||
|
ssl_sock = context.wrap_socket(sock, server_side=True)
|
||||||
|
|
||||||
|
# =====================================================================
|
||||||
|
# WSGI Middleware: Tell Flask the connection is HTTPS
|
||||||
|
#
|
||||||
|
# Waitress doesn't know the underlying socket is TLS, so Flask sees
|
||||||
|
# wsgi.url_scheme = "http". Without this middleware, force_https()
|
||||||
|
# would cause an infinite redirect loop (ERR_TOO_MANY_REDIRECTS).
|
||||||
|
# =====================================================================
|
||||||
|
class ForceHTTPSMiddleware:
|
||||||
|
"""WSGI middleware that sets url_scheme to 'https'.
|
||||||
|
|
||||||
|
Since we're wrapping the TCP socket with SSL before passing it
|
||||||
|
to Waitress, Flask's request.is_secure returns False because
|
||||||
|
Waitress reports wsgi.url_scheme='http'. This middleware fixes
|
||||||
|
that so Flask correctly identifies the connection as HTTPS.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, wsgi_app):
|
||||||
|
self.wsgi_app = wsgi_app
|
||||||
|
|
||||||
|
def __call__(self, environ, start_response):
|
||||||
|
environ['wsgi.url_scheme'] = 'https'
|
||||||
|
environ['HTTPS'] = 'on'
|
||||||
|
return self.wsgi_app(environ, start_response)
|
||||||
|
|
||||||
|
# Wrap the Flask app with the HTTPS middleware
|
||||||
|
app.wsgi_app = ForceHTTPSMiddleware(app.wsgi_app)
|
||||||
|
|
||||||
|
print(f'\n╔══════════════════════════════════════════════════════╗')
|
||||||
|
print(f'║ TEAM TRYOUTS - Development HTTPS Server ║')
|
||||||
|
print(f'╠══════════════════════════════════════════════════════╣')
|
||||||
|
print(f'║ URL: https://{host}:{port} ║')
|
||||||
|
print(f'║ Cert: self-signed (accept browser warning) ║')
|
||||||
|
print(f'║ Press Ctrl+C to stop ║')
|
||||||
|
print(f'╚══════════════════════════════════════════════════════╝\n')
|
||||||
|
|
||||||
|
# Create Waitress server with the SSL-wrapped socket
|
||||||
|
server = create_server(
|
||||||
|
app,
|
||||||
|
sockets=[ssl_sock],
|
||||||
|
threads=4,
|
||||||
|
channel_timeout=30,
|
||||||
|
)
|
||||||
|
server.run()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user