I'm having trouble rendering HTMl files in FastAPI.
main.py file
static_dir = os.path.join(os.path.dirname(__file__), "static") app.mount("/",StaticFiles(directory=static_dir, html=True),name="static") @app.get("/") async def index(): return FileResponse('index.html', media_type='text/html')
When running the above file using uvicorn, I am able to render the HTML file at http://127.0.0.1:8765/, but the static files (such as css, js and images) are not rendered.
index.html: Some code for the HTML file (built with Angular JS)
<link rel="stylesheet" href="styles.87afad25367d1df4.css" media="print" onload="this.media='all'"><noscript> <link rel="stylesheet" href="styles.87afad25367d1df4.css"></noscript></head> <body class="cui"> test <app-root></app-root> <script src="runtime.7f95ee6540776f88.js" type="module"></script> <script src="polyfills.a246e584d5c017d7.js" type="module"></script> <script src="main.4f51d0f81827a3db.js" type="module"></script> </body></html>
File structure:
modulename - static - index.html - styles.87afad25367d1df4.css - runtime.7f95ee6540776f88.js - polyfills.a246e584d5c017d7.js - main.4f51d0f81827a3db.js - main.py - __init__.py
When I open the browser console, it shows like this:
CSS/js should be rendered without containing static, e.g. http://127.0.0.1:8765/styles.87afad25367d1df4.css but it is rendering from http://127.0.0.1:8765/static/styles .87afad25367d1df4.css is loaded in the browser and run.
I'm not sure how to fix this, any help would be greatly appreciated.
Update: Added following code to explain better
main.py
import uvicorn import os import webbrowser from fastapi import FastAPI from fastapi.responses import FileResponse from fastapi.staticfiles import StaticFiles from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import HTMLResponse app = FastAPI( title="UI", description="This is to test", ) app.add_middleware( CORSMiddleware, allow_origins=['*'], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) static_dir = os.path.join(os.path.dirname(__file__), "static") app.mount("/",StaticFiles(directory=static_dir, html=True),name="static") def start_server(): # print('Starting Server...') uvicorn.run( "ui.main:app", host="0.0.0.0", port=8765, log_level="debug", reload=True, ) # webbrowser.open("http://127.0.0.1:8765/") if __name__ == "__main__": start_server()
Run this file as a package/module in the test.py file:
from ui import main if __name__ == "__main__": main.start_server()
index.html:
<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8"> <title>WingmanUi</title> <base href="static/"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" type="image/x-icon" href="favicon.ico"> <link rel="stylesheet" href="styles.87afad25367d1df4.css" media="print" onload="this.media='all'"> </head> <body> This is to test <script src="runtime.7f95ee6540776f88.js" type="module"></script> <script src="polyfills.a246e584d5c017d7.js" type="module"></script> <script src="main.4f51d0f81827a3db.js" type="module"></script> </body> </html>
File structure:
ui - static - index.html - styles.87afad25367d1df4.css - runtime.7f95ee6540776f88.js - polyfills.a246e584d5c017d7.js - main.4f51d0f81827a3db.js - main.py - __init__.py
First, when using
StaticFiles
thehtml
flag is set toTrue
so that static files are served (for dynamic web pages, see template instead), for example:You do not have to define an endpoint to serve the index page because
html=True
means running your application in HTML mode; therefore, FastAPI/Starlette will automatically loadindex.html
— See Starlette DocumentationStatic Files
. Also, if you need additional endpoints, please note that the order in which you define the endpoints within your application matters. . p>Second, since you have installed a
StaticFiles
instance and specifieddirectory='static'
, your static files are expected to be served from that directory. So, all you have to do is move all your static files as well as HTML files into thestatic
directory. You should then be able to serve static files as follows (assuming you have mounted theStaticFiles
instance to/
, e.g.app.mount('/', ...
):Alternatively, if the
StaticFiles
instance is mounted to/static
, such asapp.mount('/static', ...)
(see also This answer):In your case, the reason why static files are still loaded with
static
prefix is that you have installedStaticFiles
instance to/
, likehttp://127.0.0.1:8000/static/someScript.js
Just because you added
in the HTML document for all relative URL URL. Therefore, you should remove the following line from your HTML file: