import os from engineio.static_files import get_static_file class WSGIApp(object): """WSGI application middleware for Engine.IO. This middleware dispatches traffic to an Engine.IO application. It can also serve a list of static files to the client, or forward unrelated HTTP traffic to another WSGI application. :param engineio_app: The Engine.IO server. Must be an instance of the ``engineio.Server`` class. :param wsgi_app: The WSGI app that receives all other traffic. :param static_files: A dictionary with static file mapping rules. See the documentation for details on this argument. :param engineio_path: The endpoint where the Engine.IO application should be installed. The default value is appropriate for most cases. Example usage:: import engineio import eventlet eio = engineio.Server() app = engineio.WSGIApp(eio, static_files={ '/': {'content_type': 'text/html', 'filename': 'index.html'}, '/index.html': {'content_type': 'text/html', 'filename': 'index.html'}, }) eventlet.wsgi.server(eventlet.listen(('', 8000)), app) """ def __init__(self, engineio_app, wsgi_app=None, static_files=None, engineio_path='engine.io'): self.engineio_app = engineio_app self.wsgi_app = wsgi_app self.engineio_path = engineio_path if not self.engineio_path.startswith('/'): self.engineio_path = '/' + self.engineio_path if not self.engineio_path.endswith('/'): self.engineio_path += '/' self.static_files = static_files or {} def __call__(self, environ, start_response): if 'gunicorn.socket' in environ: # gunicorn saves the socket under environ['gunicorn.socket'], while # eventlet saves it under environ['eventlet.input']. Eventlet also # stores the socket inside a wrapper class, while gunicon writes it # directly into the environment. To give eventlet's WebSocket # module access to this socket when running under gunicorn, here we # copy the socket to the eventlet format. class Input(object): def __init__(self, socket): self.socket = socket def get_socket(self): return self.socket environ['eventlet.input'] = Input(environ['gunicorn.socket']) path = environ['PATH_INFO'] if path is not None and path.startswith(self.engineio_path): return self.engineio_app.handle_request(environ, start_response) else: static_file = get_static_file(path, self.static_files) \ if self.static_files else None if static_file and os.path.exists(static_file['filename']): start_response( '200 OK', [('Content-Type', static_file['content_type'])]) with open(static_file['filename'], 'rb') as f: return [f.read()] elif self.wsgi_app is not None: return self.wsgi_app(environ, start_response) return self.not_found(start_response) def not_found(self, start_response): start_response("404 Not Found", [('Content-Type', 'text/plain')]) return [b'Not Found'] class Middleware(WSGIApp): """This class has been renamed to ``WSGIApp`` and is now deprecated.""" def __init__(self, engineio_app, wsgi_app=None, engineio_path='engine.io'): super().__init__(engineio_app, wsgi_app, engineio_path=engineio_path)