Skip to content

Commit 80e403f

Browse files
perf: Optimize frontend localStorage key conflicts
1 parent 0341919 commit 80e403f

File tree

5 files changed

+62
-17
lines changed

5 files changed

+62
-17
lines changed

backend/common/core/response_middleware.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,17 @@ async def dispatch(self, request, call_next):
3030
direct_paths = [
3131
f"{settings.API_V1_STR}/mcp/mcp_question",
3232
f"{settings.API_V1_STR}/mcp/mcp_assistant",
33-
"/openapi.json",
34-
"/docs",
35-
"/redoc"
33+
f"{settings.CONTEXT_PATH}/openapi.json",
34+
f"{settings.CONTEXT_PATH}/docs",
35+
f"{settings.CONTEXT_PATH}/redoc"
3636
]
3737

3838
route = request.scope.get("route")
3939
# 获取定义的路径模式,例如 '/items/{item_id}'
4040
path_pattern = '' if not route else route.path_format
4141

4242
if (isinstance(response, JSONResponse)
43-
or request.url.path == f"{settings.API_V1_STR}/openapi.json"
43+
or request.url.path == f"{settings.CONTEXT_PATH}/openapi.json"
4444
or path_pattern in direct_paths):
4545
return response
4646
if response.status_code != 200:

backend/main.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ def custom_generate_unique_id(route: APIRoute) -> str:
7070

7171
app = FastAPI(
7272
title=settings.PROJECT_NAME,
73-
openapi_url=f"{settings.API_V1_STR}/openapi.json",
73+
openapi_url=f"{settings.CONTEXT_PATH}/openapi.json",
7474
generate_unique_id_function=custom_generate_unique_id,
7575
lifespan=lifespan,
7676
docs_url=None,
@@ -152,23 +152,23 @@ def generate_openapi_for_lang(lang: str) -> Dict[str, Any]:
152152

153153

154154
# custom /openapi.json and /docs
155-
@app.get("/openapi.json", include_in_schema=False)
155+
@app.get(f"{settings.CONTEXT_PATH}/openapi.json", include_in_schema=False)
156156
async def custom_openapi(request: Request):
157157
lang = get_language_from_request(request)
158158
schema = generate_openapi_for_lang(lang)
159159
return JSONResponse(schema)
160160

161161

162-
@app.get("/docs", include_in_schema=False)
162+
@app.get(f"{settings.CONTEXT_PATH}/docs", include_in_schema=False)
163163
async def custom_swagger_ui(request: Request):
164164
lang = get_language_from_request(request)
165165
from fastapi.openapi.docs import get_swagger_ui_html
166166
return get_swagger_ui_html(
167-
openapi_url=f"/openapi.json?lang={lang}",
167+
openapi_url=f"./openapi.json?lang={lang}",
168168
title="SQLBot API Docs",
169169
swagger_favicon_url="https://fastapi.tiangolo.com/img/favicon.png",
170-
swagger_js_url="/swagger-ui-bundle.js",
171-
swagger_css_url="/swagger-ui.css",
170+
swagger_js_url="./swagger-ui-bundle.js",
171+
swagger_css_url="./swagger-ui.css",
172172
)
173173

174174

frontend/public/swagger-ui-bundle.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41749,7 +41749,8 @@
4174941749
const s = new Error(a.statusText || `response status is ${a.status}`)
4175041750
// if (a.status === 401 && a.statusText === 'Unauthorized') {
4175141751
if (a.status === 401) {
41752-
location.href = location.pathname.replace('/docs', '/') + '#/401?title=unauthorized&target=docs'
41752+
location.href =
41753+
location.pathname.replace('/docs', '/') + '#/401?title=unauthorized&target=docs'
4175341754
return a
4175441755
}
4175541756
throw ((s.status = a.status), (s.statusCode = a.status), (s.response = a), s)
@@ -56482,8 +56483,15 @@
5648256483
const a = o.getConfigs().withCredentials
5648356484
o.fn.fetch.withCredentials = a
5648456485
})
56486+
function getTokenKey() {
56487+
var pathname = window.location.pathname.replace('docs', '')
56488+
var match = pathname.match(/^\/([^\/]+)/)
56489+
var prefix = match ? `${match[1]}_` : 'sqlbot_v1_'
56490+
return `${prefix}user.token`
56491+
}
5648556492
function get_token() {
56486-
var tokenCache = localStorage.getItem('user.token')
56493+
var token_key = getTokenKey()
56494+
var tokenCache = localStorage.getItem(token_key)
5648756495
if (!tokenCache) {
5648856496
return null
5648956497
}

frontend/src/components/layout/Apikey.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const handleAdd = () => {
3838
const pwd = ref('**********')
3939
const toApiDoc = () => {
4040
console.log('Add API Key')
41-
const url = '/docs'
41+
const url = './docs'
4242
window.open(url, '_blank')
4343
}
4444

frontend/src/utils/useCache.ts

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,50 @@
11
import WebStorageCache from 'web-storage-cache'
22

3-
type CacheType = 'sessionStorage' | 'localStorage'
3+
type CacheType = 'localStorage' | 'sessionStorage'
4+
5+
const getPathPrefix = () => {
6+
const pathname = window.location.pathname
7+
// eslint-disable-next-line no-useless-escape
8+
const match = pathname.match(/^\/([^\/]+)/)
9+
return match ? `${match[1]}_` : 'sqlbot_v1_'
10+
}
411

512
export const useCache = (type: CacheType = 'localStorage') => {
6-
const wsCache: WebStorageCache = new WebStorageCache({
7-
storage: type,
13+
const originalCache = new WebStorageCache({ storage: type })
14+
const prefix = getPathPrefix()
15+
16+
const methodsNeedKeyPrefix = new Set(['get', 'delete', 'touch', 'add', 'replace'])
17+
18+
const wrappedCache = new Proxy(originalCache, {
19+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
20+
get(target, prop, _receiver) {
21+
const originalMethod = target[prop as keyof typeof target]
22+
23+
if (typeof originalMethod !== 'function') {
24+
return originalMethod
25+
}
26+
27+
if (methodsNeedKeyPrefix.has(prop as string)) {
28+
return function (this: any, key: string, ...args: any[]) {
29+
// 自动加上前缀
30+
const scopedKey = `${prefix}${key}`
31+
return (originalMethod as (...args: any[]) => any).apply(target, [scopedKey, ...args])
32+
}
33+
}
34+
35+
if (prop === 'set') {
36+
return function (this: any, key: string, value: any, ...args: any[]) {
37+
const scopedKey = `${prefix}${key}`
38+
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
39+
return (originalMethod as Function).apply(target, [scopedKey, value, ...args])
40+
}
41+
}
42+
43+
return originalMethod.bind(target)
44+
},
845
})
946

1047
return {
11-
wsCache,
48+
wsCache: wrappedCache,
1249
}
1350
}

0 commit comments

Comments
 (0)