Skip to content

Commit

Permalink
default filename for static file URLs ending in '/'
Browse files Browse the repository at this point in the history
  • Loading branch information
miguelgrinberg committed Jun 3, 2019
1 parent 51f5ad2 commit a56aed1
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 7 deletions.
30 changes: 24 additions & 6 deletions docs/server.rst
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ Engine.IO servers to integrate easily into existing WSGI or ASGI applications::
Serving Static Files
--------------------

This package offers the option to configure the serving of static files. This
The Engine.IO server can be configured to serve static files to clients. This
is particularly useful to deliver HTML, CSS and JavaScript files to clients
when this package is used without a companion web framework.

Expand Down Expand Up @@ -90,20 +90,38 @@ If desired, an explicit content type for a static file can be given as follows::
'/': {'filename': 'latency.html', 'content_type': 'text/plain'},
}

Finally, it is also possible to configure an entire directory in a single rule,
so that all the files in it are served as static files::
It is also possible to configure an entire directory in a single rule, so that all
the files in it are served as static files::

static_files = {
'/static': './public',
'/': './public/index.html',
}

In this example any files with URLs starting with ``/static`` will be served
directly from the ``public`` folder in the current directory, so for example,
the URL ``/static/index.html`` will return local file ``./public/index.html``
and the URL ``/static/css/styles.css`` will return local file
``./public/css/styles.css``. The second rule creates a default mapping for the
``index.html`` file when the root URL is requested.
``./public/css/styles.css``.

If a URL that ends in a ``/`` is requested, then a default filename of
``index.html`` is appended to it. In the previous example, a request for the
``/static/`` URL would return local file ``./public/index.html``. The default
filename to serve for slash-ending URLs can be set in the static files
dictionary with an empty key::

static_files = {
'/static': './public',
'': 'image.gif',
}

With this configuration, a request for ``/static/`` would return
local file ``./public/image.gif``. A non-standard content type can also be
specified if needed::

static_files = {
'/static': './public',
'': {'filename': 'image.gif', 'content_type': 'text/plain'},
}

The static file configuration dictionary is given as the ``static_files``
argument to the ``engineio.WSGIApp`` or ``engineio.ASGIApp`` classes::
Expand Down
12 changes: 11 additions & 1 deletion engineio/static_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,19 @@ def get_static_file(path, static_files):
break
if f:
if isinstance(f, str):
ext = f.rsplit('.')[-1]
f = {'filename': f}
if f['filename'].endswith('/'):
if '' in static_files:
if isinstance(static_files[''], str):
f['filename'] += static_files['']
else:
f['filename'] += static_files['']['filename']
if 'content_type' in static_files['']:
f['content_type'] = static_files['']['content_type']
else:
f['filename'] += 'index.html'
if 'content_type' not in f:
ext = f['filename'].rsplit('.')[-1]
f['content_type'] = content_types.get(
ext, 'application/octet-stream')
return f
16 changes: 16 additions & 0 deletions tests/asyncio/test_async_asgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,22 @@ def check_path(path, status_code, content_type, body):
check_path('/static/test/index.html', 200, 'text/html',
'<html></html>\n')

app.static_files[''] = 'index.html'
check_path('/static/test/', 200, 'text/html',
'<html></html>\n')

app.static_files[''] = {'filename': 'index.html'}
check_path('/static/test/', 200, 'text/html',
'<html></html>\n')

app.static_files[''] = {'filename': 'index.html',
'content_type': 'image/gif'}
check_path('/static/test/', 200, 'image/gif',
'<html></html>\n')

app.static_files[''] = {'filename': 'test.gif'}
check_path('/static/test/', 404, 'text/plain', 'Not Found')

def test_lifespan_startup(self):
app = async_asgi.ASGIApp('eio')
scope = {'type': 'lifespan'}
Expand Down
19 changes: 19 additions & 0 deletions tests/common/test_middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,25 @@ def check_path(path, status_code, content_type, body):
'Not Found')
check_path('/static/test/index.html', '200 OK', 'text/html',
'<html></html>\n')
check_path('/static/test/', '200 OK', 'text/html',
'<html></html>\n')

m.static_files[''] = 'index.html'
check_path('/static/test/', '200 OK', 'text/html',
'<html></html>\n')

m.static_files[''] = {'filename': 'index.html'}
check_path('/static/test/', '200 OK', 'text/html',
'<html></html>\n')

m.static_files[''] = {'filename': 'index.html',
'content_type': 'image/gif'}
check_path('/static/test/', '200 OK', 'image/gif',
'<html></html>\n')

m.static_files[''] = {'filename': 'test.gif'}
check_path('/static/test/', '404 Not Found', 'text/plain',
'Not Found')

def test_404(self):
mock_wsgi_app = None
Expand Down

0 comments on commit a56aed1

Please sign in to comment.