Jason Biagio
Jason Biagio

Reputation: 61

Is there a way to explicitly set MIME types for Starlette/Uvicorn?

It appears that my simple Starlette/Uvicorn web app is serving up incorrect MIME content type for Jinja templated (served from the same server) JavaScript files. As you can see from the screen shot the uvicorn server is casting the *.js file as type (“text/plain”).

Screenshot

I have scoured the documents for both Starlette and Uvicorn and am simply stumped.

My simple web app is as follows:

from starlette.applications import Starlette
from starlette.staticfiles import StaticFiles
from starlette.responses import HTMLResponse
from starlette.templating import Jinja2Templates
from starlette.middleware.cors import CORSMiddleware
import uvicorn
from random import randint

port = randint(49152,65535)

templates = Jinja2Templates(directory='templates')


app = Starlette(debug=True)
app.mount('/static', StaticFiles(directory='statics', html=True), name='static')
app.add_middleware(
    CORSMiddleware, allow_origins=["*"], allow_headers=["*"], allow_methods=["*"]
)

@app.route('/')
async def homepage(request):
    template = "index.html"
    context = {"request": request}
    return templates.TemplateResponse(template, context, media_type='text/html')


@app.route('/error')
async def error(request):
    """
    An example error. Switch the `debug` setting to see either tracebacks or 500 pages.
    """
    raise RuntimeError("Oh no")


@app.exception_handler(404)
async def not_found(request, exc):
    """
    Return an HTTP 404 page.
    """
    template = "404.html"
    context = {"request": request}
    return templates.TemplateResponse(template, context, status_code=404)


@app.exception_handler(500)
async def server_error(request, exc):
    """
    Return an HTTP 500 page.
    """
    template = "500.html"
    context = {"request": request}
    return templates.TemplateResponse(template, context, status_code=500)


if __name__ == "__main__":
    uvicorn.run("app-567:app", host='0.0.0.0', port=port, log_level="info", http='h11', loop='asyncio', reload=True)

The JavaScript files that are loaded in the head give the same error but load nonetheless. This is a bi-product of the new 'nosniff' default setting in Firefox (73.0 64-bit). The scripts that are loaded as module imports fail outright.

I am running Windows 10 (x64), Python 3.7, uvicorn 0.11.2, and starlette 0.13.1.

Any help is greatly appreciated. Thank you in advance.

Upvotes: 3

Views: 1534

Answers (1)

Jason Biagio
Jason Biagio

Reputation: 61

I was able to fix this issue by explicitly setting the mimetypes variables as follows:

from starlette.applications import Starlette
from starlette.staticfiles import StaticFiles
from starlette.responses import HTMLResponse
from starlette.templating import Jinja2Templates
from starlette.middleware.cors import CORSMiddleware
import uvicorn
from random import randint

import mimetypes
mimetypes.init()

port = randint(49152,65535)

templates = Jinja2Templates(directory='templates')


app = Starlette(debug=True)
app.mount('/static', StaticFiles(directory='statics', html=True), name='static')
app.add_middleware(
    CORSMiddleware, allow_origins=["*"], allow_headers=["*"], allow_methods=["*"]
)

@app.route('/')
async def homepage(request):
    mimetypes.add_type('application/javascript', '.js')
    mimetypes.add_type('text/css', '.css')
    mimetypes.add_type('image/svg+xml', '.svg')
    template = "index.html"
    context = {"request": request}
    return templates.TemplateResponse(template, context, media_type='text/html')


@app.route('/error')
async def error(request):
    """
    An example error. Switch the `debug` setting to see either tracebacks or 500 pages.
    """
    raise RuntimeError("Oh no")


@app.exception_handler(404)
async def not_found(request, exc):
    """
    Return an HTTP 404 page.
    """
    template = "404.html"
    context = {"request": request}
    return templates.TemplateResponse(template, context, status_code=404)


@app.exception_handler(500)
async def server_error(request, exc):
    """
    Return an HTTP 500 page.
    """
    template = "500.html"
    context = {"request": request}
    return templates.TemplateResponse(template, context, status_code=500)


if __name__ == "__main__":
    uvicorn.run("app-567:app", host='0.0.0.0', port=port, log_level="info", http='h11', loop='asyncio', reload=True)

Upvotes: 3

Related Questions