1+ from logging .config import dictConfig
12from fastapi import FastAPI , Request
23from fastapi .middleware .cors import CORSMiddleware
4+ from fastapi .middleware .gzip import GZipMiddleware
35from fastapi .openapi .utils import get_openapi
6+ from fastapi .openapi .docs import (
7+ get_redoc_html ,
8+ get_swagger_ui_html
9+ )
10+ from fastapi .staticfiles import StaticFiles
411from starlette .middleware .base import BaseHTTPMiddleware
12+ from starlette .responses import PlainTextResponse
13+ from sqlalchemy .exc import TimeoutError , DatabaseError
514
615from app .api .endpoints import router
716from app .core .config import settings
@@ -12,19 +21,27 @@ async def db_middleware(request: Request, call_next) -> None:
1221 """
1322 Middleware that wraps each API call in a transaction
1423 """
15- with SessionLocal () as db_session :
16- request .state .db = db_session
24+ ROUTE_PREFIX_WHITELIST = ("/api/v1/firehose" )
25+ if request .url .path .startswith (ROUTE_PREFIX_WHITELIST ):
26+ return await call_next (request )
27+ else :
28+ try :
29+ with SessionLocal () as db_session :
30+ request .state .db = db_session
31+ response = await call_next (request )
32+ if response .status_code >= 500 :
33+ db_session .rollback ()
34+ else :
1735
18- response = await call_next (request )
19- if response .status_code >= 500 :
20- db_session .rollback ()
21- else :
36+ db_session .commit ()
2237
23- db_session .commit ()
24-
25- if hasattr (request .state , "audit_logger" ) and request .state .audit_logger :
26- request .state .audit_logger .save_audits (db_session )
27- db_session .commit ()
38+ if hasattr (request .state , "audit_logger" ) and request .state .audit_logger :
39+ request .state .audit_logger .save_audits (db_session )
40+ db_session .commit ()
41+ except TimeoutError :
42+ return TextResponse (503 , "Timeout when connecting to database" )
43+ except DatabaseError :
44+ return TextResponse (500 , "Error when connecting to database" )
2845
2946 return response
3047
@@ -33,18 +50,42 @@ def create_app() -> FastAPI:
3350 """
3451 :return:
3552 """
53+ # Set up logging format
54+ # dictConfig({
55+ # "version": 1,
56+ # "disable_existing_loggers": False,
57+ # "formatters": {
58+ # "access": {
59+ # "()": "uvicorn.logging.AccessFormatter",
60+ # "fmt": '%(asctime)s - %(levelprefix)s %(client_addr)s - \"%(request_line)s\" %(status_code)s',
61+ # "use_colors": True
62+ # },
63+ # },
64+ # "handlers": {
65+ # "access": {
66+ # "formatter": "access",
67+ # "class": "logging.StreamHandler",
68+ # "stream": "ext://sys.stdout",
69+ # },
70+ # },
71+ # "loggers": {
72+ # "uvicorn.access": {
73+ # "handlers": ["access"],
74+ # "level": "INFO",
75+ # "propagate": False
76+ # },
77+ # },
78+ # })
79+
3680 app = FastAPI (
3781 debug = settings .DEBUG ,
38- title = settings .TITLE ,
39- description = settings .DESCRIPTION ,
40- docs_url = settings .DOCS_URL ,
41- openapi_url = settings .OPENAPI_URL ,
42- redoc_url = settings .REDOC_URL ,
43- swagger_ui_parameters = {
44- "filter" : True
45- }
82+ docs_url = None ,
83+ redoc_url = None ,
84+ openapi_url = settings .OPENAPI_URL
4685 )
4786
87+ app .mount ('/api/static' , StaticFiles (packages = [('app.api' , 'static' )]), name = 'static' )
88+
4889 app .include_router (router .api_router , prefix = settings .API_V1_STR )
4990
5091 app .add_middleware (
@@ -56,13 +97,18 @@ def create_app() -> FastAPI:
5697 allow_headers = ["*" ],
5798 )
5899
100+ app .add_middleware (
101+ GZipMiddleware ,
102+ minimum_size = 500 ,
103+ compresslevel = 5 )
104+
59105 app .add_middleware (BaseHTTPMiddleware , dispatch = db_middleware )
60106
61107 if not app .openapi_schema :
62108 # will need to update all links for open source stuff
63109 openapi_schema = get_openapi (
64110 title = "SCOT" ,
65- version = "4.2 .0" ,
111+ version = "4.4 .0" ,
66112 summary = "Sandia Cyber Omni Tracker Server" ,
67113 description = "The Sandia Cyber Omni Tracker (SCOT) is a cyber security incident response management system and knowledge base. Designed by cyber security incident responders, SCOT provides a new approach to manage security alerts, analyze data for deeper patterns, coordinate team efforts, and capture team knowledge. SCOT integrates with existing security applications to provide a consistent, easy to use interface that enhances analyst effectiveness." ,
68114 routes = app .routes ,
@@ -82,4 +128,24 @@ def create_app() -> FastAPI:
82128 }
83129 app .openapi_schema = openapi_schema
84130
131+ @app .get (settings .DOCS_URL , include_in_schema = False )
132+ async def custom_swagger_ui_html ():
133+ return get_swagger_ui_html (
134+ openapi_url = settings .OPENAPI_URL ,
135+ title = settings .TITLE ,
136+ swagger_js_url = settings .SWAGGER_JS_URL ,
137+ swagger_css_url = settings .SWAGGER_CSS_URL ,
138+ swagger_ui_parameters = {
139+ "filter" : True
140+ }
141+ )
142+
143+ @app .get (settings .REDOC_URL , include_in_schema = False )
144+ async def redoc_html ():
145+ return get_redoc_html (
146+ openapi_url = settings .OPENAPI_URL ,
147+ title = settings .TITLE ,
148+ redoc_js_url = settings .REDOC_JS_URL ,
149+ )
150+
85151 return app
0 commit comments