mirror of
https://github.com/iflytek/skillhub.git
synced 2026-10-09 03:17:52 +00:00
Merge pull request #226 from iflytek/fix/issue-223-nginx-prefix
fix(web): preserve nginx subpath prefix for api/runtime config
This commit is contained in:
commit
8cb783406d
3 changed files with 49 additions and 5 deletions
|
|
@ -36,6 +36,7 @@ vi.mock('@/shared/lib/api-error', () => ({
|
|||
import {
|
||||
WEB_API_PREFIX,
|
||||
buildApiUrl,
|
||||
fetchText,
|
||||
getDirectAuthRuntimeConfig,
|
||||
getSessionBootstrapRuntimeConfig,
|
||||
} from './client'
|
||||
|
|
@ -45,6 +46,8 @@ beforeEach(() => {
|
|||
})
|
||||
|
||||
afterEach(() => {
|
||||
vi.unstubAllGlobals()
|
||||
|
||||
if (originalWindow) {
|
||||
Object.defineProperty(globalThis, 'window', {
|
||||
configurable: true,
|
||||
|
|
@ -79,6 +82,38 @@ describe('buildApiUrl', () => {
|
|||
const url = buildApiUrl('/api/v1/auth/me')
|
||||
expect(url).toBe('https://api.example.com/api/v1/auth/me')
|
||||
})
|
||||
|
||||
it('preserves base URL path prefixes', () => {
|
||||
window.__SKILLHUB_RUNTIME_CONFIG__ = { apiBaseUrl: 'https://api.example.com/skill_hub' }
|
||||
const url = buildApiUrl('/api/v1/auth/me')
|
||||
expect(url).toBe('https://api.example.com/skill_hub/api/v1/auth/me')
|
||||
})
|
||||
|
||||
it('supports relative base URL path prefixes', () => {
|
||||
window.__SKILLHUB_RUNTIME_CONFIG__ = { apiBaseUrl: '/skill_hub' }
|
||||
const url = buildApiUrl('/api/v1/auth/me')
|
||||
expect(url).toBe('/skill_hub/api/v1/auth/me')
|
||||
})
|
||||
})
|
||||
|
||||
describe('fetchText', () => {
|
||||
it('applies base URL path prefixes for fetch requests', async () => {
|
||||
window.__SKILLHUB_RUNTIME_CONFIG__ = { apiBaseUrl: 'https://api.example.com/skill_hub' }
|
||||
const fetchMock = vi.fn().mockResolvedValue({
|
||||
ok: true,
|
||||
text: async () => 'ok',
|
||||
})
|
||||
vi.stubGlobal('fetch', fetchMock)
|
||||
|
||||
await fetchText('/api/v1/auth/me')
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledWith(
|
||||
'https://api.example.com/skill_hub/api/v1/auth/me',
|
||||
expect.objectContaining({
|
||||
headers: expect.any(Headers),
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('getDirectAuthRuntimeConfig', () => {
|
||||
|
|
|
|||
|
|
@ -252,7 +252,7 @@ function withBaseUrl(input: RequestInfo | URL): RequestInfo | URL {
|
|||
if (!baseUrl || typeof input !== 'string' || !input.startsWith('/')) {
|
||||
return input
|
||||
}
|
||||
return new URL(input, ensureTrailingSlash(baseUrl))
|
||||
return prependApiBaseUrl(baseUrl, input)
|
||||
}
|
||||
|
||||
export function buildApiUrl(path: string): string {
|
||||
|
|
@ -260,11 +260,20 @@ export function buildApiUrl(path: string): string {
|
|||
if (!baseUrl) {
|
||||
return path
|
||||
}
|
||||
return new URL(path, ensureTrailingSlash(baseUrl)).toString()
|
||||
return prependApiBaseUrl(baseUrl, path)
|
||||
}
|
||||
|
||||
function ensureTrailingSlash(value: string): string {
|
||||
return value.endsWith('/') ? value : `${value}/`
|
||||
function prependApiBaseUrl(baseUrl: string, path: string): string {
|
||||
const normalizedBaseUrl = trimTrailingSlash(baseUrl)
|
||||
const normalizedPath = path.startsWith('/') ? path : `/${path}`
|
||||
return `${normalizedBaseUrl}${normalizedPath}`
|
||||
}
|
||||
|
||||
function trimTrailingSlash(value: string): string {
|
||||
if (value.length > 1 && value.endsWith('/')) {
|
||||
return value.slice(0, -1)
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
export async function getCurrentUser(): Promise<User | null> {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
async function loadRuntimeConfig() {
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const script = document.createElement('script')
|
||||
script.src = '/runtime-config.js'
|
||||
script.src = new URL('../runtime-config.js', import.meta.url).toString()
|
||||
script.async = false
|
||||
script.onload = () => resolve()
|
||||
script.onerror = () => reject(new Error('Failed to load runtime config'))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue