You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
86 lines
3.7 KiB
86 lines
3.7 KiB
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)
|
|
|