mirror of
https://github.com/langgenius/dify.git
synced 2026-03-12 18:57:02 +00:00
Compare commits
4 Commits
main
...
3-12-vite-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f530b1647b | ||
|
|
5b300aa5c9 | ||
|
|
4985e245d4 | ||
|
|
bfe11c89cf |
@@ -12,6 +12,9 @@ NEXT_PUBLIC_API_PREFIX=http://localhost:5001/console/api
|
||||
# console or api domain.
|
||||
# example: http://udify.app/api
|
||||
NEXT_PUBLIC_PUBLIC_API_PREFIX=http://localhost:5001/api
|
||||
# Dev-only Vite proxy targets. Use these when routing same-origin requests through the local dev server.
|
||||
VITE_CONSOLE_API_PROXY_TARGET=https://cloud.dify.ai
|
||||
VITE_PUBLIC_API_PROXY_TARGET=https://cloud.dify.ai
|
||||
# When the frontend and backend run on different subdomains, set NEXT_PUBLIC_COOKIE_DOMAIN=1.
|
||||
NEXT_PUBLIC_COOKIE_DOMAIN=
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import { cva } from 'class-variance-authority'
|
||||
import * as React from 'react'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import Divider from '../divider'
|
||||
import './index.css'
|
||||
|
||||
type SegmentedControlOption<T> = {
|
||||
value: T
|
||||
@@ -131,7 +130,7 @@ export const SegmentedControl = <T extends string | number | symbol>({
|
||||
<div className={cn('inline-flex items-center gap-x-1', ItemTextWrapperVariants({ size }))}>
|
||||
<span>{text}</span>
|
||||
{!!(count && size === 'large') && (
|
||||
<div className="system-2xs-medium-uppercase inline-flex h-[18px] min-w-[18px] items-center justify-center rounded-[5px] border border-divider-deep bg-components-badge-bg-dimm px-[5px] text-text-tertiary">
|
||||
<div className="inline-flex h-[18px] min-w-[18px] items-center justify-center rounded-[5px] border border-divider-deep bg-components-badge-bg-dimm px-[5px] text-text-tertiary system-2xs-medium-uppercase">
|
||||
{count}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
@import "../components/base/button/index.css";
|
||||
@import "../components/base/modal/index.css";
|
||||
@import "../components/base/premium-badge/index.css";
|
||||
@import "../components/base/segmented-control/index.css";
|
||||
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
|
||||
@@ -2657,11 +2657,6 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"app/components/base/segmented-control/index.tsx": {
|
||||
"tailwindcss/enforce-consistent-class-order": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"app/components/base/select/custom.tsx": {
|
||||
"tailwindcss/enforce-consistent-class-order": {
|
||||
"count": 2
|
||||
|
||||
130
web/plugins/vite/proxy.ts
Normal file
130
web/plugins/vite/proxy.ts
Normal file
@@ -0,0 +1,130 @@
|
||||
import type { ProxyOptions } from 'vite'
|
||||
|
||||
const DEFAULT_PROXY_TARGET = 'https://cloud.dify.ai'
|
||||
|
||||
const SECURE_COOKIE_PREFIX_PATTERN = /^__(Host|Secure)-/
|
||||
const SAME_SITE_NONE_PATTERN = /^samesite=none$/i
|
||||
const COOKIE_PATH_PATTERN = /^path=/i
|
||||
const COOKIE_DOMAIN_PATTERN = /^domain=/i
|
||||
const COOKIE_SECURE_PATTERN = /^secure$/i
|
||||
const COOKIE_PARTITIONED_PATTERN = /^partitioned$/i
|
||||
|
||||
const HOST_PREFIX_COOKIE_NAMES = new Set([
|
||||
'access_token',
|
||||
'csrf_token',
|
||||
'refresh_token',
|
||||
'webapp_access_token',
|
||||
])
|
||||
|
||||
const isPassportCookie = (cookieName: string) => cookieName.startsWith('passport-')
|
||||
|
||||
const shouldUseHostPrefix = (cookieName: string) => {
|
||||
const normalizedCookieName = cookieName.replace(SECURE_COOKIE_PREFIX_PATTERN, '')
|
||||
return HOST_PREFIX_COOKIE_NAMES.has(normalizedCookieName) || isPassportCookie(normalizedCookieName)
|
||||
}
|
||||
|
||||
const toCloudCookieName = (cookieName: string) => {
|
||||
if (cookieName.startsWith('__Host-'))
|
||||
return cookieName
|
||||
|
||||
if (cookieName.startsWith('__Secure-'))
|
||||
return `__Host-${cookieName.replace(SECURE_COOKIE_PREFIX_PATTERN, '')}`
|
||||
|
||||
if (!shouldUseHostPrefix(cookieName))
|
||||
return cookieName
|
||||
|
||||
return `__Host-${cookieName}`
|
||||
}
|
||||
|
||||
const toLocalCookieName = (cookieName: string) => cookieName.replace(SECURE_COOKIE_PREFIX_PATTERN, '')
|
||||
|
||||
export const rewriteCookieHeaderForCloud = (cookieHeader?: string) => {
|
||||
if (!cookieHeader)
|
||||
return cookieHeader
|
||||
|
||||
return cookieHeader
|
||||
.split(/;\s*/)
|
||||
.filter(Boolean)
|
||||
.map((cookie) => {
|
||||
const separatorIndex = cookie.indexOf('=')
|
||||
if (separatorIndex === -1)
|
||||
return cookie
|
||||
|
||||
const cookieName = cookie.slice(0, separatorIndex).trim()
|
||||
const cookieValue = cookie.slice(separatorIndex + 1)
|
||||
return `${toCloudCookieName(cookieName)}=${cookieValue}`
|
||||
})
|
||||
.join('; ')
|
||||
}
|
||||
|
||||
const rewriteSetCookieValueForLocal = (setCookieValue: string) => {
|
||||
const [rawCookiePair, ...rawAttributes] = setCookieValue.split(';')
|
||||
const separatorIndex = rawCookiePair.indexOf('=')
|
||||
|
||||
if (separatorIndex === -1)
|
||||
return setCookieValue
|
||||
|
||||
const cookieName = rawCookiePair.slice(0, separatorIndex).trim()
|
||||
const cookieValue = rawCookiePair.slice(separatorIndex + 1)
|
||||
const rewrittenAttributes = rawAttributes
|
||||
.map(attribute => attribute.trim())
|
||||
.filter(attribute =>
|
||||
!COOKIE_DOMAIN_PATTERN.test(attribute)
|
||||
&& !COOKIE_SECURE_PATTERN.test(attribute)
|
||||
&& !COOKIE_PARTITIONED_PATTERN.test(attribute),
|
||||
)
|
||||
.map((attribute) => {
|
||||
if (SAME_SITE_NONE_PATTERN.test(attribute))
|
||||
return 'SameSite=Lax'
|
||||
|
||||
if (COOKIE_PATH_PATTERN.test(attribute))
|
||||
return 'Path=/'
|
||||
|
||||
return attribute
|
||||
})
|
||||
|
||||
return [`${toLocalCookieName(cookieName)}=${cookieValue}`, ...rewrittenAttributes].join('; ')
|
||||
}
|
||||
|
||||
export const rewriteSetCookieHeadersForLocal = (setCookieHeaders?: string | string[]): string[] | undefined => {
|
||||
if (!setCookieHeaders)
|
||||
return undefined
|
||||
|
||||
const normalizedHeaders = Array.isArray(setCookieHeaders)
|
||||
? setCookieHeaders
|
||||
: [setCookieHeaders]
|
||||
|
||||
return normalizedHeaders.map(rewriteSetCookieValueForLocal)
|
||||
}
|
||||
|
||||
const createCookieAwareProxy = (target = DEFAULT_PROXY_TARGET): ProxyOptions => ({
|
||||
target,
|
||||
changeOrigin: true,
|
||||
secure: true,
|
||||
configure(proxy) {
|
||||
proxy.on('proxyReq', (proxyReq, request) => {
|
||||
const cookieHeader = rewriteCookieHeaderForCloud(request.headers.cookie)
|
||||
if (cookieHeader)
|
||||
proxyReq.setHeader('cookie', cookieHeader)
|
||||
})
|
||||
|
||||
proxy.on('proxyRes', (proxyRes) => {
|
||||
const rewrittenSetCookieHeaders = rewriteSetCookieHeadersForLocal(proxyRes.headers['set-cookie'])
|
||||
if (rewrittenSetCookieHeaders)
|
||||
proxyRes.headers['set-cookie'] = rewrittenSetCookieHeaders
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
export const createDevProxyConfig = (options?: {
|
||||
consoleApiTarget?: string
|
||||
publicApiTarget?: string
|
||||
}) => {
|
||||
const consoleApiTarget = options?.consoleApiTarget || DEFAULT_PROXY_TARGET
|
||||
const publicApiTarget = options?.publicApiTarget || consoleApiTarget
|
||||
|
||||
return {
|
||||
'/console/api': createCookieAwareProxy(consoleApiTarget),
|
||||
'/api': createCookieAwareProxy(publicApiTarget),
|
||||
} satisfies Record<string, ProxyOptions>
|
||||
}
|
||||
@@ -2,17 +2,19 @@ import path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import react from '@vitejs/plugin-react'
|
||||
import vinext from 'vinext'
|
||||
import { defineConfig } from 'vite'
|
||||
import { defineConfig, loadEnv } from 'vite'
|
||||
import Inspect from 'vite-plugin-inspect'
|
||||
import tsconfigPaths from 'vite-tsconfig-paths'
|
||||
import { createCodeInspectorPlugin, createForceInspectorClientInjectionPlugin } from './plugins/vite/code-inspector'
|
||||
import { customI18nHmrPlugin } from './plugins/vite/custom-i18n-hmr'
|
||||
import { createDevProxyConfig } from './plugins/vite/proxy'
|
||||
|
||||
const projectRoot = path.dirname(fileURLToPath(import.meta.url))
|
||||
const isCI = !!process.env.CI
|
||||
const browserInitializerInjectTarget = path.resolve(projectRoot, 'app/components/browser-initializer.tsx')
|
||||
|
||||
export default defineConfig(({ mode }) => {
|
||||
const env = loadEnv(mode, projectRoot, '')
|
||||
const isTest = mode === 'test'
|
||||
const isStorybook = process.env.STORYBOOK === 'true'
|
||||
|| process.argv.some(arg => arg.toLowerCase().includes('storybook'))
|
||||
@@ -65,6 +67,10 @@ export default defineConfig(({ mode }) => {
|
||||
},
|
||||
server: {
|
||||
port: 3000,
|
||||
proxy: createDevProxyConfig({
|
||||
consoleApiTarget: env.VITE_CONSOLE_API_PROXY_TARGET,
|
||||
publicApiTarget: env.VITE_PUBLIC_API_PROXY_TARGET,
|
||||
}),
|
||||
},
|
||||
ssr: {
|
||||
// SyntaxError: Named export not found. The requested module is a CommonJS module, which may not support all module.exports as named exports
|
||||
|
||||
Reference in New Issue
Block a user