@@ -34,6 +34,8 @@ pip install -e .
3434
3535## Quick Usage
3636
37+ ### Single User
38+
3739``` python
3840from fastapi import FastAPI
3941from fastapi_docshield import DocShield
@@ -44,13 +46,145 @@ app = FastAPI()
4446def read_root ():
4547 return {" Hello" : " World" }
4648
47- # Add protection to docs
49+ # Add protection to docs with a single user
4850DocShield(
4951 app = app,
5052 credentials = {" admin" : " password123" }
5153)
5254```
5355
56+ ### Multiple Users
57+
58+ ``` python
59+ from fastapi import FastAPI
60+ from fastapi_docshield import DocShield
61+
62+ app = FastAPI()
63+
64+ @app.get (" /" )
65+ def read_root ():
66+ return {" Hello" : " World" }
67+
68+ # Add protection to docs with multiple users
69+ DocShield(
70+ app = app,
71+ credentials = {
72+ " admin" : " admin_password" ,
73+ " developer" : " dev_password" ,
74+ " viewer" : " viewer_password"
75+ }
76+ )
77+ ```
78+
79+ ### CDN Fallback Mode (Default)
80+
81+ ``` python
82+ from fastapi import FastAPI
83+ from fastapi_docshield import DocShield
84+
85+ app = FastAPI()
86+
87+ # Default mode: Use CDN with automatic fallback to local files
88+ DocShield(
89+ app = app,
90+ credentials = {" admin" : " password123" },
91+ use_cdn_fallback = True # Default - automatically falls back to local if CDN fails
92+ )
93+ ```
94+
95+ ### Prefer Local Files
96+
97+ ``` python
98+ from fastapi import FastAPI
99+ from fastapi_docshield import DocShield
100+
101+ app = FastAPI()
102+
103+ # Always use local files instead of CDN
104+ DocShield(
105+ app = app,
106+ credentials = {" admin" : " password123" },
107+ prefer_local = True # Serve documentation from bundled static files
108+ )
109+ ```
110+
111+ ### CDN Only (No Fallback)
112+
113+ ``` python
114+ from fastapi import FastAPI
115+ from fastapi_docshield import DocShield
116+
117+ app = FastAPI()
118+
119+ # Use CDN without fallback (original behavior)
120+ DocShield(
121+ app = app,
122+ credentials = {" admin" : " password123" },
123+ use_cdn_fallback = False # Disable fallback, CDN only
124+ )
125+ ```
126+
127+ ### Custom CSS and JavaScript
128+
129+ ``` python
130+ from fastapi import FastAPI
131+ from fastapi_docshield import DocShield
132+ import requests
133+
134+ app = FastAPI()
135+
136+ # Load dark theme CSS from external source
137+ # You can use https://github.com/georgekhananaev/fastapi-swagger-dark
138+ dark_theme_url = " https://raw.githubusercontent.com/georgekhananaev/fastapi-swagger-dark/main/src/fastapi_swagger_dark/swagger_ui_dark.min.css"
139+ custom_css = requests.get(dark_theme_url).text
140+
141+ # Custom JavaScript for analytics
142+ custom_js = """
143+ console.log('📊 Documentation accessed at:', new Date().toISOString());
144+ document.addEventListener('DOMContentLoaded', function() {
145+ console.log('Dark theme loaded!');
146+ });
147+ """
148+
149+ # Apply with custom styling
150+ DocShield(
151+ app = app,
152+ credentials = {" admin" : " password123" },
153+ custom_css = custom_css,
154+ custom_js = custom_js
155+ )
156+ ```
157+
158+ #### Using with fastapi-swagger-dark
159+
160+ For a complete dark theme solution, you can use the [ fastapi-swagger-dark] ( https://github.com/georgekhananaev/fastapi-swagger-dark ) package:
161+
162+ ``` python
163+ from fastapi import FastAPI
164+ from fastapi_docshield import DocShield
165+ import requests
166+
167+ app = FastAPI()
168+
169+ # Fetch dark theme CSS
170+ response = requests.get(
171+ " https://raw.githubusercontent.com/georgekhananaev/fastapi-swagger-dark/main/src/fastapi_swagger_dark/swagger_ui_dark.min.css"
172+ )
173+ dark_css = response.text
174+
175+ DocShield(
176+ app = app,
177+ credentials = {" admin" : " password123" },
178+ custom_css = dark_css # Apply dark theme
179+ )
180+ ```
181+
182+ See [ examples/custom_styling.py] ( examples/custom_styling.py ) for more customization examples including:
183+ - ✨ Minimal clean theme
184+ - 🏢 Corporate theme with analytics
185+ - 📖 ReDoc customization
186+ - 🎨 Custom branding
187+
54188## Running Demo
55189
56190``` bash
@@ -80,9 +214,36 @@ pytest --cov=fastapi_docshield
80214- Protect Swagger UI, ReDoc, and OpenAPI JSON endpoints
81215- Customizable endpoint URLs
82216- Multiple username/password combinations
217+ - ** Automatic CDN fallback** - Falls back to local files if CDN is unavailable
218+ - ** Local file preference option** - Serve documentation from local files for better reliability
219+ - ** Custom CSS and JavaScript injection** - Fully customize the look and behavior of documentation
220+ - ** Resilient documentation** - Works even when CDN is down or blocked
83221- Tested on Python 3.7-3.13
84222- Compatible with uv package manager
85223
224+ ## Changelog
225+
226+ ### Version 0.2.0 (2025-08-17)
227+ - ** Added** : Custom CSS and JavaScript injection support
228+ - New ` custom_css ` parameter to inject custom styles into documentation pages
229+ - New ` custom_js ` parameter to inject custom JavaScript for enhanced functionality
230+ - Complete customization examples for dark theme, minimal theme, corporate branding, and analytics
231+ - Support for both Swagger UI and ReDoc customization
232+ - ** Added** : Automatic CDN fallback to local files for better reliability
233+ - Documentation now automatically falls back to bundled static files if CDN is unavailable
234+ - New ` prefer_local ` option to always serve from local files
235+ - New ` use_cdn_fallback ` option to control fallback behavior
236+ - Bundled Swagger UI and ReDoc static files for offline capability
237+ - ** Fixed** : Static file URL bug that caused blank documentation pages
238+ - Previously, when no custom CDN URLs were provided, the package would pass ` None ` values to FastAPI's documentation functions
239+ - This resulted in HTML with ` href="None" ` and ` src="None" ` , causing white/blank pages
240+ - Now properly handles default CDN URLs when custom URLs are not specified
241+
242+ ### Version 0.1.0 (2025-01-15)
243+ - Initial release
244+ - Basic HTTP authentication for FastAPI documentation endpoints
245+ - Support for multiple users
246+
86247## License
87248
88249MIT License - Copyright (c) 2025 George Khananaev
0 commit comments