mirror of
https://github.com/langgenius/dify.git
synced 2026-04-19 18:27:27 +08:00
Compare commits
1 Commits
1.13.2
...
3-18-dev-w
| Author | SHA1 | Date | |
|---|---|---|---|
| dacba93e00 |
@ -12,7 +12,7 @@ NEXT_PUBLIC_API_PREFIX=http://localhost:5001/console/api
|
|||||||
# console or api domain.
|
# console or api domain.
|
||||||
# example: http://udify.app/api
|
# example: http://udify.app/api
|
||||||
NEXT_PUBLIC_PUBLIC_API_PREFIX=http://localhost:5001/api
|
NEXT_PUBLIC_PUBLIC_API_PREFIX=http://localhost:5001/api
|
||||||
# Dev-only Hono proxy targets. The frontend keeps requesting http://localhost:5001 directly.
|
# Dev-only Hono proxy targets. Set the api prefixes above to https://localhost:5001/... to start the proxy with HTTPS.
|
||||||
HONO_PROXY_HOST=127.0.0.1
|
HONO_PROXY_HOST=127.0.0.1
|
||||||
HONO_PROXY_PORT=5001
|
HONO_PROXY_PORT=5001
|
||||||
HONO_CONSOLE_API_PROXY_TARGET=
|
HONO_CONSOLE_API_PROXY_TARGET=
|
||||||
|
|||||||
@ -210,6 +210,7 @@
|
|||||||
"@types/sortablejs": "1.15.9",
|
"@types/sortablejs": "1.15.9",
|
||||||
"@typescript-eslint/parser": "8.57.0",
|
"@typescript-eslint/parser": "8.57.0",
|
||||||
"@typescript/native-preview": "7.0.0-dev.20260312.1",
|
"@typescript/native-preview": "7.0.0-dev.20260312.1",
|
||||||
|
"@vitejs/plugin-basic-ssl": "2.2.0",
|
||||||
"@vitejs/plugin-react": "6.0.0",
|
"@vitejs/plugin-react": "6.0.0",
|
||||||
"@vitejs/plugin-rsc": "0.5.21",
|
"@vitejs/plugin-rsc": "0.5.21",
|
||||||
"@vitest/coverage-v8": "4.1.0",
|
"@vitest/coverage-v8": "4.1.0",
|
||||||
|
|||||||
@ -34,7 +34,16 @@ const toUpstreamCookieName = (cookieName: string) => {
|
|||||||
return `__Host-${cookieName}`
|
return `__Host-${cookieName}`
|
||||||
}
|
}
|
||||||
|
|
||||||
const toLocalCookieName = (cookieName: string) => cookieName.replace(SECURE_COOKIE_PREFIX_PATTERN, '')
|
const toLocalCookieName = (cookieName: string, options: LocalCookieRewriteOptions) => {
|
||||||
|
if (options.localSecure)
|
||||||
|
return cookieName
|
||||||
|
|
||||||
|
return cookieName.replace(SECURE_COOKIE_PREFIX_PATTERN, '')
|
||||||
|
}
|
||||||
|
|
||||||
|
type LocalCookieRewriteOptions = {
|
||||||
|
localSecure: boolean
|
||||||
|
}
|
||||||
|
|
||||||
export const rewriteCookieHeaderForUpstream = (cookieHeader?: string) => {
|
export const rewriteCookieHeaderForUpstream = (cookieHeader?: string) => {
|
||||||
if (!cookieHeader)
|
if (!cookieHeader)
|
||||||
@ -55,7 +64,10 @@ export const rewriteCookieHeaderForUpstream = (cookieHeader?: string) => {
|
|||||||
.join('; ')
|
.join('; ')
|
||||||
}
|
}
|
||||||
|
|
||||||
const rewriteSetCookieValueForLocal = (setCookieValue: string) => {
|
const rewriteSetCookieValueForLocal = (
|
||||||
|
setCookieValue: string,
|
||||||
|
options: LocalCookieRewriteOptions,
|
||||||
|
) => {
|
||||||
const [rawCookiePair, ...rawAttributes] = setCookieValue.split(';')
|
const [rawCookiePair, ...rawAttributes] = setCookieValue.split(';')
|
||||||
const separatorIndex = rawCookiePair.indexOf('=')
|
const separatorIndex = rawCookiePair.indexOf('=')
|
||||||
|
|
||||||
@ -68,11 +80,11 @@ const rewriteSetCookieValueForLocal = (setCookieValue: string) => {
|
|||||||
.map(attribute => attribute.trim())
|
.map(attribute => attribute.trim())
|
||||||
.filter(attribute =>
|
.filter(attribute =>
|
||||||
!COOKIE_DOMAIN_PATTERN.test(attribute)
|
!COOKIE_DOMAIN_PATTERN.test(attribute)
|
||||||
&& !COOKIE_SECURE_PATTERN.test(attribute)
|
&& (options.localSecure || !COOKIE_SECURE_PATTERN.test(attribute))
|
||||||
&& !COOKIE_PARTITIONED_PATTERN.test(attribute),
|
&& (options.localSecure || !COOKIE_PARTITIONED_PATTERN.test(attribute)),
|
||||||
)
|
)
|
||||||
.map((attribute) => {
|
.map((attribute) => {
|
||||||
if (SAME_SITE_NONE_PATTERN.test(attribute))
|
if (!options.localSecure && SAME_SITE_NONE_PATTERN.test(attribute))
|
||||||
return 'SameSite=Lax'
|
return 'SameSite=Lax'
|
||||||
|
|
||||||
if (COOKIE_PATH_PATTERN.test(attribute))
|
if (COOKIE_PATH_PATTERN.test(attribute))
|
||||||
@ -81,10 +93,13 @@ const rewriteSetCookieValueForLocal = (setCookieValue: string) => {
|
|||||||
return attribute
|
return attribute
|
||||||
})
|
})
|
||||||
|
|
||||||
return [`${toLocalCookieName(cookieName)}=${cookieValue}`, ...rewrittenAttributes].join('; ')
|
return [`${toLocalCookieName(cookieName, options)}=${cookieValue}`, ...rewrittenAttributes].join('; ')
|
||||||
}
|
}
|
||||||
|
|
||||||
export const rewriteSetCookieHeadersForLocal = (setCookieHeaders?: string | string[]): string[] | undefined => {
|
export const rewriteSetCookieHeadersForLocal = (
|
||||||
|
setCookieHeaders: string | string[] | undefined,
|
||||||
|
options: LocalCookieRewriteOptions,
|
||||||
|
): string[] | undefined => {
|
||||||
if (!setCookieHeaders)
|
if (!setCookieHeaders)
|
||||||
return undefined
|
return undefined
|
||||||
|
|
||||||
@ -92,7 +107,7 @@ export const rewriteSetCookieHeadersForLocal = (setCookieHeaders?: string | stri
|
|||||||
? setCookieHeaders
|
? setCookieHeaders
|
||||||
: [setCookieHeaders]
|
: [setCookieHeaders]
|
||||||
|
|
||||||
return normalizedHeaders.map(rewriteSetCookieValueForLocal)
|
return normalizedHeaders.map(setCookieValue => rewriteSetCookieValueForLocal(setCookieValue, options))
|
||||||
}
|
}
|
||||||
|
|
||||||
export { DEFAULT_PROXY_TARGET }
|
export { DEFAULT_PROXY_TARGET }
|
||||||
|
|||||||
21
web/plugins/dev-proxy/protocol.ts
Normal file
21
web/plugins/dev-proxy/protocol.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
export type DevProxyProtocolEnv = Partial<Record<
|
||||||
|
| 'NEXT_PUBLIC_API_PREFIX'
|
||||||
|
| 'NEXT_PUBLIC_PUBLIC_API_PREFIX',
|
||||||
|
string
|
||||||
|
>>
|
||||||
|
|
||||||
|
const isHttpsUrl = (value?: string) => {
|
||||||
|
if (!value)
|
||||||
|
return false
|
||||||
|
|
||||||
|
try {
|
||||||
|
return new URL(value).protocol === 'https:'
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const shouldUseHttpsForDevProxy = (env: DevProxyProtocolEnv = {}) => {
|
||||||
|
return isHttpsUrl(env.NEXT_PUBLIC_API_PREFIX) || isHttpsUrl(env.NEXT_PUBLIC_PUBLIC_API_PREFIX)
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||||
import { buildUpstreamUrl, createDevProxyApp, isAllowedDevOrigin, resolveDevProxyTargets } from './server'
|
import { buildUpstreamUrl, createDevProxyApp, isAllowedDevOrigin, resolveDevProxyTargets, shouldUseHttpsForDevProxy } from './server'
|
||||||
|
|
||||||
describe('dev proxy server', () => {
|
describe('dev proxy server', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@ -19,6 +19,21 @@ describe('dev proxy server', () => {
|
|||||||
expect(targets.publicApiTarget).toBe('https://public.example.com')
|
expect(targets.publicApiTarget).toBe('https://public.example.com')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Scenario: the local dev proxy should switch to https when api prefixes are configured with https.
|
||||||
|
it('should enable https for the local dev proxy when api prefixes use https', () => {
|
||||||
|
// Assert
|
||||||
|
expect(shouldUseHttpsForDevProxy({
|
||||||
|
NEXT_PUBLIC_API_PREFIX: 'https://localhost:5001/console/api',
|
||||||
|
})).toBe(true)
|
||||||
|
expect(shouldUseHttpsForDevProxy({
|
||||||
|
NEXT_PUBLIC_PUBLIC_API_PREFIX: 'https://localhost:5001/api',
|
||||||
|
})).toBe(true)
|
||||||
|
expect(shouldUseHttpsForDevProxy({
|
||||||
|
NEXT_PUBLIC_API_PREFIX: 'http://localhost:5001/console/api',
|
||||||
|
NEXT_PUBLIC_PUBLIC_API_PREFIX: 'http://localhost:5001/api',
|
||||||
|
})).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
// Scenario: target paths should not be duplicated when the incoming route already includes them.
|
// Scenario: target paths should not be duplicated when the incoming route already includes them.
|
||||||
it('should preserve prefixed targets when building upstream URLs', () => {
|
it('should preserve prefixed targets when building upstream URLs', () => {
|
||||||
// Act
|
// Act
|
||||||
@ -32,6 +47,7 @@ describe('dev proxy server', () => {
|
|||||||
it('should only allow local development origins', () => {
|
it('should only allow local development origins', () => {
|
||||||
// Assert
|
// Assert
|
||||||
expect(isAllowedDevOrigin('http://localhost:3000')).toBe(true)
|
expect(isAllowedDevOrigin('http://localhost:3000')).toBe(true)
|
||||||
|
expect(isAllowedDevOrigin('https://localhost:3000')).toBe(true)
|
||||||
expect(isAllowedDevOrigin('http://127.0.0.1:3000')).toBe(true)
|
expect(isAllowedDevOrigin('http://127.0.0.1:3000')).toBe(true)
|
||||||
expect(isAllowedDevOrigin('https://example.com')).toBe(false)
|
expect(isAllowedDevOrigin('https://example.com')).toBe(false)
|
||||||
})
|
})
|
||||||
@ -86,6 +102,39 @@ describe('dev proxy server', () => {
|
|||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Scenario: secure local proxy responses should keep secure cross-site cookie attributes intact.
|
||||||
|
it('should preserve secure cookie attributes when the local proxy is https', async () => {
|
||||||
|
// Arrange
|
||||||
|
const fetchImpl = vi.fn<typeof fetch>().mockResolvedValue(new Response('ok', {
|
||||||
|
status: 200,
|
||||||
|
headers: [
|
||||||
|
['set-cookie', '__Host-access_token=abc; Path=/console/api; Domain=cloud.dify.ai; Secure; SameSite=None; Partitioned'],
|
||||||
|
['set-cookie', '__Host-csrf_token=csrf; Path=/console/api; Domain=cloud.dify.ai; Secure; SameSite=None'],
|
||||||
|
],
|
||||||
|
}))
|
||||||
|
const app = createDevProxyApp({
|
||||||
|
consoleApiTarget: 'https://cloud.dify.ai',
|
||||||
|
publicApiTarget: 'https://public.dify.ai',
|
||||||
|
fetchImpl,
|
||||||
|
})
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const response = await app.request('https://127.0.0.1:5001/console/api/apps?page=1', {
|
||||||
|
headers: {
|
||||||
|
Origin: 'https://localhost:3000',
|
||||||
|
Cookie: 'access_token=abc',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(response.headers.getSetCookie()).toEqual([
|
||||||
|
'__Host-access_token=abc; Path=/; Secure; SameSite=None; Partitioned',
|
||||||
|
'__Host-csrf_token=csrf; Path=/; Secure; SameSite=None',
|
||||||
|
])
|
||||||
|
expect(response.headers.get('access-control-allow-origin')).toBe('https://localhost:3000')
|
||||||
|
expect(response.headers.get('access-control-allow-credentials')).toBe('true')
|
||||||
|
})
|
||||||
|
|
||||||
// Scenario: preflight requests should advertise allowed headers for credentialed cross-origin calls.
|
// Scenario: preflight requests should advertise allowed headers for credentialed cross-origin calls.
|
||||||
it('should answer CORS preflight requests', async () => {
|
it('should answer CORS preflight requests', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
|
|||||||
@ -2,10 +2,16 @@ import type { Context, Hono } from 'hono'
|
|||||||
import { Hono as HonoApp } from 'hono'
|
import { Hono as HonoApp } from 'hono'
|
||||||
import { DEFAULT_PROXY_TARGET, rewriteCookieHeaderForUpstream, rewriteSetCookieHeadersForLocal } from './cookies'
|
import { DEFAULT_PROXY_TARGET, rewriteCookieHeaderForUpstream, rewriteSetCookieHeadersForLocal } from './cookies'
|
||||||
|
|
||||||
|
export { shouldUseHttpsForDevProxy } from './protocol'
|
||||||
|
|
||||||
type DevProxyEnv = Partial<Record<
|
type DevProxyEnv = Partial<Record<
|
||||||
| 'HONO_CONSOLE_API_PROXY_TARGET'
|
| 'HONO_CONSOLE_API_PROXY_TARGET'
|
||||||
| 'HONO_PUBLIC_API_PROXY_TARGET',
|
| 'HONO_PUBLIC_API_PROXY_TARGET',
|
||||||
string
|
string
|
||||||
|
> & Record<
|
||||||
|
| 'NEXT_PUBLIC_API_PREFIX'
|
||||||
|
| 'NEXT_PUBLIC_PUBLIC_API_PREFIX',
|
||||||
|
string | undefined
|
||||||
>>
|
>>
|
||||||
|
|
||||||
export type DevProxyTargets = {
|
export type DevProxyTargets = {
|
||||||
@ -93,11 +99,15 @@ const createProxyRequestHeaders = (request: Request, targetUrl: URL) => {
|
|||||||
return headers
|
return headers
|
||||||
}
|
}
|
||||||
|
|
||||||
const createUpstreamResponseHeaders = (response: Response, requestOrigin?: string | null) => {
|
const createUpstreamResponseHeaders = (
|
||||||
|
response: Response,
|
||||||
|
requestOrigin: string | null | undefined,
|
||||||
|
localSecure: boolean,
|
||||||
|
) => {
|
||||||
const headers = new Headers(response.headers)
|
const headers = new Headers(response.headers)
|
||||||
RESPONSE_HEADERS_TO_DROP.forEach(header => headers.delete(header))
|
RESPONSE_HEADERS_TO_DROP.forEach(header => headers.delete(header))
|
||||||
|
|
||||||
const rewrittenSetCookies = rewriteSetCookieHeadersForLocal(response.headers.getSetCookie())
|
const rewrittenSetCookies = rewriteSetCookieHeadersForLocal(response.headers.getSetCookie(), { localSecure })
|
||||||
rewrittenSetCookies?.forEach((cookie) => {
|
rewrittenSetCookies?.forEach((cookie) => {
|
||||||
headers.append('set-cookie', cookie)
|
headers.append('set-cookie', cookie)
|
||||||
})
|
})
|
||||||
@ -126,7 +136,11 @@ const proxyRequest = async (
|
|||||||
}
|
}
|
||||||
|
|
||||||
const upstreamResponse = await fetchImpl(targetUrl, requestInit)
|
const upstreamResponse = await fetchImpl(targetUrl, requestInit)
|
||||||
const responseHeaders = createUpstreamResponseHeaders(upstreamResponse, context.req.header('origin'))
|
const responseHeaders = createUpstreamResponseHeaders(
|
||||||
|
upstreamResponse,
|
||||||
|
context.req.header('origin'),
|
||||||
|
requestUrl.protocol === 'https:',
|
||||||
|
)
|
||||||
|
|
||||||
return new Response(upstreamResponse.body, {
|
return new Response(upstreamResponse.body, {
|
||||||
status: upstreamResponse.status,
|
status: upstreamResponse.status,
|
||||||
|
|||||||
13
web/pnpm-lock.yaml
generated
13
web/pnpm-lock.yaml
generated
@ -512,6 +512,9 @@ importers:
|
|||||||
'@typescript/native-preview':
|
'@typescript/native-preview':
|
||||||
specifier: 7.0.0-dev.20260312.1
|
specifier: 7.0.0-dev.20260312.1
|
||||||
version: 7.0.0-dev.20260312.1
|
version: 7.0.0-dev.20260312.1
|
||||||
|
'@vitejs/plugin-basic-ssl':
|
||||||
|
specifier: 2.2.0
|
||||||
|
version: 2.2.0(@voidzero-dev/vite-plus-core@0.1.11(@types/node@25.5.0)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2))
|
||||||
'@vitejs/plugin-react':
|
'@vitejs/plugin-react':
|
||||||
specifier: 6.0.0
|
specifier: 6.0.0
|
||||||
version: 6.0.0(@voidzero-dev/vite-plus-core@0.1.11(@types/node@25.5.0)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2))
|
version: 6.0.0(@voidzero-dev/vite-plus-core@0.1.11(@types/node@25.5.0)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2))
|
||||||
@ -3603,6 +3606,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-hBcWIOppZV14bi+eAmCZj8Elj8hVSUZJTpf1lgGBhVD85pervzQ1poM/qYfFUlPraYSZYP+ASg6To5BwYmUSGQ==}
|
resolution: {integrity: sha512-hBcWIOppZV14bi+eAmCZj8Elj8hVSUZJTpf1lgGBhVD85pervzQ1poM/qYfFUlPraYSZYP+ASg6To5BwYmUSGQ==}
|
||||||
engines: {node: '>=16'}
|
engines: {node: '>=16'}
|
||||||
|
|
||||||
|
'@vitejs/plugin-basic-ssl@2.2.0':
|
||||||
|
resolution: {integrity: sha512-nmyQ1HGRkfUxjsv3jw0+hMhEdZdrtkvMTdkzRUaRWfiO6PCWw2V2Pz3gldCq96Tn9S8htcgdTxw/gmbLLEbfYw==}
|
||||||
|
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
|
||||||
|
peerDependencies:
|
||||||
|
vite: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||||
|
|
||||||
'@vitejs/plugin-react@5.2.0':
|
'@vitejs/plugin-react@5.2.0':
|
||||||
resolution: {integrity: sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw==}
|
resolution: {integrity: sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw==}
|
||||||
engines: {node: ^20.19.0 || >=22.12.0}
|
engines: {node: ^20.19.0 || >=22.12.0}
|
||||||
@ -11030,6 +11039,10 @@ snapshots:
|
|||||||
'@resvg/resvg-wasm': 2.4.0
|
'@resvg/resvg-wasm': 2.4.0
|
||||||
satori: 0.16.0
|
satori: 0.16.0
|
||||||
|
|
||||||
|
'@vitejs/plugin-basic-ssl@2.2.0(@voidzero-dev/vite-plus-core@0.1.11(@types/node@25.5.0)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2))':
|
||||||
|
dependencies:
|
||||||
|
vite: '@voidzero-dev/vite-plus-core@0.1.11(@types/node@25.5.0)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)'
|
||||||
|
|
||||||
'@vitejs/plugin-react@5.2.0(@voidzero-dev/vite-plus-core@0.1.11(@types/node@25.5.0)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2))':
|
'@vitejs/plugin-react@5.2.0(@voidzero-dev/vite-plus-core@0.1.11(@types/node@25.5.0)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.98.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0
|
'@babel/core': 7.29.0
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
|
import { createSecureServer } from 'node:http2'
|
||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
import { fileURLToPath } from 'node:url'
|
import { fileURLToPath } from 'node:url'
|
||||||
import { serve } from '@hono/node-server'
|
import { serve } from '@hono/node-server'
|
||||||
|
import { getCertificate } from '@vitejs/plugin-basic-ssl'
|
||||||
import { loadEnv } from 'vite'
|
import { loadEnv } from 'vite'
|
||||||
import { createDevProxyApp, resolveDevProxyTargets } from '../plugins/dev-proxy/server'
|
import { createDevProxyApp, resolveDevProxyTargets, shouldUseHttpsForDevProxy } from '../plugins/dev-proxy/server'
|
||||||
|
|
||||||
const projectRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
|
const projectRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
|
||||||
const mode = process.env.MODE || process.env.NODE_ENV || 'development'
|
const mode = process.env.MODE || process.env.NODE_ENV || 'development'
|
||||||
@ -11,11 +13,33 @@ const env = loadEnv(mode, projectRoot, '')
|
|||||||
const host = env.HONO_PROXY_HOST || '127.0.0.1'
|
const host = env.HONO_PROXY_HOST || '127.0.0.1'
|
||||||
const port = Number(env.HONO_PROXY_PORT || 5001)
|
const port = Number(env.HONO_PROXY_PORT || 5001)
|
||||||
const app = createDevProxyApp(resolveDevProxyTargets(env))
|
const app = createDevProxyApp(resolveDevProxyTargets(env))
|
||||||
|
const useHttps = shouldUseHttpsForDevProxy(env)
|
||||||
|
|
||||||
serve({
|
if (useHttps) {
|
||||||
fetch: app.fetch,
|
const certificate = await getCertificate(
|
||||||
hostname: host,
|
path.join(projectRoot, 'node_modules/.vite/basic-ssl'),
|
||||||
port,
|
'localhost',
|
||||||
})
|
Array.from(new Set(['localhost', '127.0.0.1', host])),
|
||||||
|
)
|
||||||
|
|
||||||
console.log(`[dev-hono-proxy] listening on http://${host}:${port}`)
|
serve({
|
||||||
|
fetch: app.fetch,
|
||||||
|
hostname: host,
|
||||||
|
port,
|
||||||
|
createServer: createSecureServer,
|
||||||
|
serverOptions: {
|
||||||
|
allowHTTP1: true,
|
||||||
|
cert: certificate,
|
||||||
|
key: certificate,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
serve({
|
||||||
|
fetch: app.fetch,
|
||||||
|
hostname: host,
|
||||||
|
port,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`[dev-hono-proxy] listening on ${useHttps ? 'https' : 'http'}://${host}:${port}`)
|
||||||
|
|||||||
@ -1,9 +1,12 @@
|
|||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
import { fileURLToPath } from 'node:url'
|
import { fileURLToPath } from 'node:url'
|
||||||
|
import basicSsl from '@vitejs/plugin-basic-ssl'
|
||||||
import react from '@vitejs/plugin-react'
|
import react from '@vitejs/plugin-react'
|
||||||
import vinext from 'vinext'
|
import vinext from 'vinext'
|
||||||
|
import { loadEnv } from 'vite'
|
||||||
import Inspect from 'vite-plugin-inspect'
|
import Inspect from 'vite-plugin-inspect'
|
||||||
import { defineConfig } from 'vite-plus'
|
import { defineConfig } from 'vite-plus'
|
||||||
|
import { shouldUseHttpsForDevProxy } from './plugins/dev-proxy/protocol'
|
||||||
import { createCodeInspectorPlugin, createForceInspectorClientInjectionPlugin } from './plugins/vite/code-inspector'
|
import { createCodeInspectorPlugin, createForceInspectorClientInjectionPlugin } from './plugins/vite/code-inspector'
|
||||||
import { customI18nHmrPlugin } from './plugins/vite/custom-i18n-hmr'
|
import { customI18nHmrPlugin } from './plugins/vite/custom-i18n-hmr'
|
||||||
import { nextStaticImageTestPlugin } from './plugins/vite/next-static-image-test'
|
import { nextStaticImageTestPlugin } from './plugins/vite/next-static-image-test'
|
||||||
@ -21,6 +24,8 @@ export default defineConfig(({ mode }) => {
|
|||||||
const isTest = mode === 'test'
|
const isTest = mode === 'test'
|
||||||
const isStorybook = process.env.STORYBOOK === 'true'
|
const isStorybook = process.env.STORYBOOK === 'true'
|
||||||
|| process.argv.some(arg => arg.toLowerCase().includes('storybook'))
|
|| process.argv.some(arg => arg.toLowerCase().includes('storybook'))
|
||||||
|
const env = loadEnv(mode, projectRoot, '')
|
||||||
|
const useHttpsForDevServer = shouldUseHttpsForDevProxy(env)
|
||||||
const isAppComponentsCoverage = coverageScope === 'app-components'
|
const isAppComponentsCoverage = coverageScope === 'app-components'
|
||||||
const excludedComponentCoverageFiles = isAppComponentsCoverage
|
const excludedComponentCoverageFiles = isAppComponentsCoverage
|
||||||
? collectComponentCoverageExcludedFiles(path.join(projectRoot, 'app/components'), { pathPrefix: 'app/components' })
|
? collectComponentCoverageExcludedFiles(path.join(projectRoot, 'app/components'), { pathPrefix: 'app/components' })
|
||||||
@ -57,6 +62,7 @@ export default defineConfig(({ mode }) => {
|
|||||||
react(),
|
react(),
|
||||||
vinext({ react: false }),
|
vinext({ react: false }),
|
||||||
customI18nHmrPlugin({ injectTarget: browserInitializerInjectTarget }),
|
customI18nHmrPlugin({ injectTarget: browserInitializerInjectTarget }),
|
||||||
|
...(useHttpsForDevServer ? [basicSsl()] : []),
|
||||||
// reactGrabOpenFilePlugin({
|
// reactGrabOpenFilePlugin({
|
||||||
// injectTarget: browserInitializerInjectTarget,
|
// injectTarget: browserInitializerInjectTarget,
|
||||||
// projectRoot,
|
// projectRoot,
|
||||||
|
|||||||
Reference in New Issue
Block a user