mirror of
https://github.com/langgenius/dify.git
synced 2026-03-18 13:57:03 +00:00
Compare commits
2 Commits
3-18-dev-w
...
1.13.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f943f1e39b | ||
|
|
239e09473e |
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "dify-api"
|
||||
version = "1.13.0"
|
||||
version = "1.13.1"
|
||||
requires-python = ">=3.11,<3.13"
|
||||
|
||||
dependencies = [
|
||||
|
||||
2
api/uv.lock
generated
2
api/uv.lock
generated
@@ -1533,7 +1533,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "dify-api"
|
||||
version = "1.13.0"
|
||||
version = "1.13.1"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "aliyun-log-python-sdk" },
|
||||
|
||||
@@ -21,7 +21,7 @@ services:
|
||||
|
||||
# API service
|
||||
api:
|
||||
image: langgenius/dify-api:1.13.0
|
||||
image: langgenius/dify-api:1.13.1
|
||||
restart: always
|
||||
environment:
|
||||
# Use the shared environment variables.
|
||||
@@ -63,7 +63,7 @@ services:
|
||||
# worker service
|
||||
# The Celery worker for processing all queues (dataset, workflow, mail, etc.)
|
||||
worker:
|
||||
image: langgenius/dify-api:1.13.0
|
||||
image: langgenius/dify-api:1.13.1
|
||||
restart: always
|
||||
environment:
|
||||
# Use the shared environment variables.
|
||||
@@ -102,7 +102,7 @@ services:
|
||||
# worker_beat service
|
||||
# Celery beat for scheduling periodic tasks.
|
||||
worker_beat:
|
||||
image: langgenius/dify-api:1.13.0
|
||||
image: langgenius/dify-api:1.13.1
|
||||
restart: always
|
||||
environment:
|
||||
# Use the shared environment variables.
|
||||
@@ -132,7 +132,7 @@ services:
|
||||
|
||||
# Frontend web application.
|
||||
web:
|
||||
image: langgenius/dify-web:1.13.0
|
||||
image: langgenius/dify-web:1.13.1
|
||||
restart: always
|
||||
environment:
|
||||
CONSOLE_API_URL: ${CONSOLE_API_URL:-}
|
||||
|
||||
@@ -728,7 +728,7 @@ services:
|
||||
|
||||
# API service
|
||||
api:
|
||||
image: langgenius/dify-api:1.13.0
|
||||
image: langgenius/dify-api:1.13.1
|
||||
restart: always
|
||||
environment:
|
||||
# Use the shared environment variables.
|
||||
@@ -770,7 +770,7 @@ services:
|
||||
# worker service
|
||||
# The Celery worker for processing all queues (dataset, workflow, mail, etc.)
|
||||
worker:
|
||||
image: langgenius/dify-api:1.13.0
|
||||
image: langgenius/dify-api:1.13.1
|
||||
restart: always
|
||||
environment:
|
||||
# Use the shared environment variables.
|
||||
@@ -809,7 +809,7 @@ services:
|
||||
# worker_beat service
|
||||
# Celery beat for scheduling periodic tasks.
|
||||
worker_beat:
|
||||
image: langgenius/dify-api:1.13.0
|
||||
image: langgenius/dify-api:1.13.1
|
||||
restart: always
|
||||
environment:
|
||||
# Use the shared environment variables.
|
||||
@@ -839,7 +839,7 @@ services:
|
||||
|
||||
# Frontend web application.
|
||||
web:
|
||||
image: langgenius/dify-web:1.13.0
|
||||
image: langgenius/dify-web:1.13.1
|
||||
restart: always
|
||||
environment:
|
||||
CONSOLE_API_URL: ${CONSOLE_API_URL:-}
|
||||
|
||||
@@ -12,7 +12,7 @@ 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 Hono proxy targets. Set the api prefixes above to https://localhost:5001/... to start the proxy with HTTPS.
|
||||
# Dev-only Hono proxy targets. The frontend keeps requesting http://localhost:5001 directly.
|
||||
HONO_PROXY_HOST=127.0.0.1
|
||||
HONO_PROXY_PORT=5001
|
||||
HONO_CONSOLE_API_PROXY_TARGET=
|
||||
|
||||
@@ -328,7 +328,7 @@ describe('createWorkflowStreamHandlers', () => {
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
const setupHandlers = (overrides: { isTimedOut?: () => boolean } = {}) => {
|
||||
const setupHandlers = (overrides: { isPublicAPI?: boolean, isTimedOut?: () => boolean } = {}) => {
|
||||
let completionRes = ''
|
||||
let currentTaskId: string | null = null
|
||||
let isStopping = false
|
||||
@@ -359,6 +359,7 @@ describe('createWorkflowStreamHandlers', () => {
|
||||
const handlers = createWorkflowStreamHandlers({
|
||||
getCompletionRes: () => completionRes,
|
||||
getWorkflowProcessData: () => workflowProcessData,
|
||||
isPublicAPI: overrides.isPublicAPI ?? false,
|
||||
isTimedOut: overrides.isTimedOut ?? (() => false),
|
||||
markEnded,
|
||||
notify,
|
||||
@@ -391,7 +392,7 @@ describe('createWorkflowStreamHandlers', () => {
|
||||
}
|
||||
|
||||
it('should process workflow success and paused events', () => {
|
||||
const setup = setupHandlers()
|
||||
const setup = setupHandlers({ isPublicAPI: true })
|
||||
const handlers = setup.handlers as Required<Pick<IOtherOptions, 'onWorkflowStarted' | 'onTextChunk' | 'onHumanInputRequired' | 'onHumanInputFormFilled' | 'onHumanInputFormTimeout' | 'onWorkflowPaused' | 'onWorkflowFinished' | 'onNodeStarted' | 'onNodeFinished' | 'onIterationStart' | 'onIterationNext' | 'onIterationFinish' | 'onLoopStart' | 'onLoopNext' | 'onLoopFinish'>>
|
||||
|
||||
act(() => {
|
||||
@@ -546,7 +547,11 @@ describe('createWorkflowStreamHandlers', () => {
|
||||
resultText: 'Hello',
|
||||
status: WorkflowRunningStatus.Succeeded,
|
||||
}))
|
||||
expect(sseGetMock).toHaveBeenCalledWith('/workflow/run-1/events', {}, expect.any(Object))
|
||||
expect(sseGetMock).toHaveBeenCalledWith(
|
||||
'/workflow/run-1/events',
|
||||
{},
|
||||
expect.objectContaining({ isPublicAPI: true }),
|
||||
)
|
||||
expect(setup.messageId()).toBe('run-1')
|
||||
expect(setup.onCompleted).toHaveBeenCalledWith('{"answer":"Hello"}', 3, true)
|
||||
expect(setup.setRespondingFalse).toHaveBeenCalled()
|
||||
@@ -647,6 +652,7 @@ describe('createWorkflowStreamHandlers', () => {
|
||||
const handlers = createWorkflowStreamHandlers({
|
||||
getCompletionRes: () => '',
|
||||
getWorkflowProcessData: () => existingProcess,
|
||||
isPublicAPI: false,
|
||||
isTimedOut: () => false,
|
||||
markEnded: vi.fn(),
|
||||
notify: setup.notify,
|
||||
|
||||
@@ -351,6 +351,7 @@ describe('useResultSender', () => {
|
||||
await waitFor(() => {
|
||||
expect(createWorkflowStreamHandlersMock).toHaveBeenCalledWith(expect.objectContaining({
|
||||
getCompletionRes: harness.runState.getCompletionRes,
|
||||
isPublicAPI: true,
|
||||
resetRunState: harness.runState.resetRunState,
|
||||
setWorkflowProcessData: harness.runState.setWorkflowProcessData,
|
||||
}))
|
||||
@@ -373,6 +374,30 @@ describe('useResultSender', () => {
|
||||
expect(harness.runState.clearMoreLikeThis).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should configure workflow handlers for installed apps as non-public', async () => {
|
||||
const harness = createRunStateHarness()
|
||||
|
||||
const { result } = renderSender({
|
||||
appSourceType: AppSourceTypeEnum.installedApp,
|
||||
isWorkflow: true,
|
||||
runState: harness.runState,
|
||||
})
|
||||
|
||||
await act(async () => {
|
||||
expect(await result.current.handleSend()).toBe(true)
|
||||
})
|
||||
|
||||
expect(createWorkflowStreamHandlersMock).toHaveBeenCalledWith(expect.objectContaining({
|
||||
isPublicAPI: false,
|
||||
}))
|
||||
expect(sendWorkflowMessageMock).toHaveBeenCalledWith(
|
||||
{ inputs: { name: 'Alice' } },
|
||||
expect.any(Object),
|
||||
AppSourceTypeEnum.installedApp,
|
||||
'app-1',
|
||||
)
|
||||
})
|
||||
|
||||
it('should stringify non-Error workflow failures', async () => {
|
||||
const harness = createRunStateHarness()
|
||||
sendWorkflowMessageMock.mockRejectedValue('workflow failed')
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import type { ResultInputValue } from '../result-request'
|
||||
import type { ResultRunStateController } from './use-result-run-state'
|
||||
import type { PromptConfig } from '@/models/debug'
|
||||
import type { AppSourceType } from '@/service/share'
|
||||
import type { VisionFile, VisionSettings } from '@/types/app'
|
||||
import { useCallback, useEffect, useRef } from 'react'
|
||||
import { TEXT_GENERATION_TIMEOUT_MS } from '@/config'
|
||||
import {
|
||||
AppSourceType,
|
||||
sendCompletionMessage,
|
||||
sendWorkflowMessage,
|
||||
} from '@/service/share'
|
||||
@@ -117,6 +117,7 @@ export const useResultSender = ({
|
||||
const otherOptions = createWorkflowStreamHandlers({
|
||||
getCompletionRes: runState.getCompletionRes,
|
||||
getWorkflowProcessData: runState.getWorkflowProcessData,
|
||||
isPublicAPI: appSourceType === AppSourceType.webApp,
|
||||
isTimedOut: () => isTimeout,
|
||||
markEnded: () => {
|
||||
isEnd = true
|
||||
|
||||
@@ -13,6 +13,7 @@ type Translate = (key: string, options?: Record<string, unknown>) => string
|
||||
type CreateWorkflowStreamHandlersParams = {
|
||||
getCompletionRes: () => string
|
||||
getWorkflowProcessData: () => WorkflowProcess | undefined
|
||||
isPublicAPI: boolean
|
||||
isTimedOut: () => boolean
|
||||
markEnded: () => void
|
||||
notify: Notify
|
||||
@@ -255,6 +256,7 @@ const serializeWorkflowOutputs = (outputs: WorkflowFinishedResponse['data']['out
|
||||
export const createWorkflowStreamHandlers = ({
|
||||
getCompletionRes,
|
||||
getWorkflowProcessData,
|
||||
isPublicAPI,
|
||||
isTimedOut,
|
||||
markEnded,
|
||||
notify,
|
||||
@@ -287,6 +289,7 @@ export const createWorkflowStreamHandlers = ({
|
||||
}
|
||||
|
||||
const otherOptions: IOtherOptions = {
|
||||
isPublicAPI,
|
||||
onWorkflowStarted: ({ workflow_run_id, task_id }) => {
|
||||
const workflowProcessData = getWorkflowProcessData()
|
||||
if (workflowProcessData?.tracing.length) {
|
||||
@@ -378,6 +381,7 @@ export const createWorkflowStreamHandlers = ({
|
||||
},
|
||||
onWorkflowPaused: ({ data }) => {
|
||||
tempMessageId = data.workflow_run_id
|
||||
// WebApp workflows must keep using the public API namespace after pause/resume.
|
||||
void sseGet(`/workflow/${data.workflow_run_id}/events`, {}, otherOptions)
|
||||
setWorkflowProcessData(applyWorkflowPaused(getWorkflowProcessData()))
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "dify-web",
|
||||
"type": "module",
|
||||
"version": "1.13.0",
|
||||
"version": "1.13.1",
|
||||
"private": true,
|
||||
"packageManager": "pnpm@10.32.1",
|
||||
"imports": {
|
||||
@@ -210,7 +210,6 @@
|
||||
"@types/sortablejs": "1.15.9",
|
||||
"@typescript-eslint/parser": "8.57.0",
|
||||
"@typescript/native-preview": "7.0.0-dev.20260312.1",
|
||||
"@vitejs/plugin-basic-ssl": "2.2.0",
|
||||
"@vitejs/plugin-react": "6.0.0",
|
||||
"@vitejs/plugin-rsc": "0.5.21",
|
||||
"@vitest/coverage-v8": "4.1.0",
|
||||
|
||||
@@ -34,16 +34,7 @@ const toUpstreamCookieName = (cookieName: string) => {
|
||||
return `__Host-${cookieName}`
|
||||
}
|
||||
|
||||
const toLocalCookieName = (cookieName: string, options: LocalCookieRewriteOptions) => {
|
||||
if (options.localSecure)
|
||||
return cookieName
|
||||
|
||||
return cookieName.replace(SECURE_COOKIE_PREFIX_PATTERN, '')
|
||||
}
|
||||
|
||||
type LocalCookieRewriteOptions = {
|
||||
localSecure: boolean
|
||||
}
|
||||
const toLocalCookieName = (cookieName: string) => cookieName.replace(SECURE_COOKIE_PREFIX_PATTERN, '')
|
||||
|
||||
export const rewriteCookieHeaderForUpstream = (cookieHeader?: string) => {
|
||||
if (!cookieHeader)
|
||||
@@ -64,10 +55,7 @@ export const rewriteCookieHeaderForUpstream = (cookieHeader?: string) => {
|
||||
.join('; ')
|
||||
}
|
||||
|
||||
const rewriteSetCookieValueForLocal = (
|
||||
setCookieValue: string,
|
||||
options: LocalCookieRewriteOptions,
|
||||
) => {
|
||||
const rewriteSetCookieValueForLocal = (setCookieValue: string) => {
|
||||
const [rawCookiePair, ...rawAttributes] = setCookieValue.split(';')
|
||||
const separatorIndex = rawCookiePair.indexOf('=')
|
||||
|
||||
@@ -80,11 +68,11 @@ const rewriteSetCookieValueForLocal = (
|
||||
.map(attribute => attribute.trim())
|
||||
.filter(attribute =>
|
||||
!COOKIE_DOMAIN_PATTERN.test(attribute)
|
||||
&& (options.localSecure || !COOKIE_SECURE_PATTERN.test(attribute))
|
||||
&& (options.localSecure || !COOKIE_PARTITIONED_PATTERN.test(attribute)),
|
||||
&& !COOKIE_SECURE_PATTERN.test(attribute)
|
||||
&& !COOKIE_PARTITIONED_PATTERN.test(attribute),
|
||||
)
|
||||
.map((attribute) => {
|
||||
if (!options.localSecure && SAME_SITE_NONE_PATTERN.test(attribute))
|
||||
if (SAME_SITE_NONE_PATTERN.test(attribute))
|
||||
return 'SameSite=Lax'
|
||||
|
||||
if (COOKIE_PATH_PATTERN.test(attribute))
|
||||
@@ -93,13 +81,10 @@ const rewriteSetCookieValueForLocal = (
|
||||
return attribute
|
||||
})
|
||||
|
||||
return [`${toLocalCookieName(cookieName, options)}=${cookieValue}`, ...rewrittenAttributes].join('; ')
|
||||
return [`${toLocalCookieName(cookieName)}=${cookieValue}`, ...rewrittenAttributes].join('; ')
|
||||
}
|
||||
|
||||
export const rewriteSetCookieHeadersForLocal = (
|
||||
setCookieHeaders: string | string[] | undefined,
|
||||
options: LocalCookieRewriteOptions,
|
||||
): string[] | undefined => {
|
||||
export const rewriteSetCookieHeadersForLocal = (setCookieHeaders?: string | string[]): string[] | undefined => {
|
||||
if (!setCookieHeaders)
|
||||
return undefined
|
||||
|
||||
@@ -107,7 +92,7 @@ export const rewriteSetCookieHeadersForLocal = (
|
||||
? setCookieHeaders
|
||||
: [setCookieHeaders]
|
||||
|
||||
return normalizedHeaders.map(setCookieValue => rewriteSetCookieValueForLocal(setCookieValue, options))
|
||||
return normalizedHeaders.map(rewriteSetCookieValueForLocal)
|
||||
}
|
||||
|
||||
export { DEFAULT_PROXY_TARGET }
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
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 { buildUpstreamUrl, createDevProxyApp, isAllowedDevOrigin, resolveDevProxyTargets, shouldUseHttpsForDevProxy } from './server'
|
||||
import { buildUpstreamUrl, createDevProxyApp, isAllowedDevOrigin, resolveDevProxyTargets } from './server'
|
||||
|
||||
describe('dev proxy server', () => {
|
||||
beforeEach(() => {
|
||||
@@ -19,21 +19,6 @@ describe('dev proxy server', () => {
|
||||
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.
|
||||
it('should preserve prefixed targets when building upstream URLs', () => {
|
||||
// Act
|
||||
@@ -47,7 +32,6 @@ describe('dev proxy server', () => {
|
||||
it('should only allow local development origins', () => {
|
||||
// Assert
|
||||
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('https://example.com')).toBe(false)
|
||||
})
|
||||
@@ -102,39 +86,6 @@ 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.
|
||||
it('should answer CORS preflight requests', async () => {
|
||||
// Arrange
|
||||
|
||||
@@ -2,16 +2,10 @@ import type { Context, Hono } from 'hono'
|
||||
import { Hono as HonoApp } from 'hono'
|
||||
import { DEFAULT_PROXY_TARGET, rewriteCookieHeaderForUpstream, rewriteSetCookieHeadersForLocal } from './cookies'
|
||||
|
||||
export { shouldUseHttpsForDevProxy } from './protocol'
|
||||
|
||||
type DevProxyEnv = Partial<Record<
|
||||
| 'HONO_CONSOLE_API_PROXY_TARGET'
|
||||
| 'HONO_PUBLIC_API_PROXY_TARGET',
|
||||
string
|
||||
> & Record<
|
||||
| 'NEXT_PUBLIC_API_PREFIX'
|
||||
| 'NEXT_PUBLIC_PUBLIC_API_PREFIX',
|
||||
string | undefined
|
||||
>>
|
||||
|
||||
export type DevProxyTargets = {
|
||||
@@ -99,15 +93,11 @@ const createProxyRequestHeaders = (request: Request, targetUrl: URL) => {
|
||||
return headers
|
||||
}
|
||||
|
||||
const createUpstreamResponseHeaders = (
|
||||
response: Response,
|
||||
requestOrigin: string | null | undefined,
|
||||
localSecure: boolean,
|
||||
) => {
|
||||
const createUpstreamResponseHeaders = (response: Response, requestOrigin?: string | null) => {
|
||||
const headers = new Headers(response.headers)
|
||||
RESPONSE_HEADERS_TO_DROP.forEach(header => headers.delete(header))
|
||||
|
||||
const rewrittenSetCookies = rewriteSetCookieHeadersForLocal(response.headers.getSetCookie(), { localSecure })
|
||||
const rewrittenSetCookies = rewriteSetCookieHeadersForLocal(response.headers.getSetCookie())
|
||||
rewrittenSetCookies?.forEach((cookie) => {
|
||||
headers.append('set-cookie', cookie)
|
||||
})
|
||||
@@ -136,11 +126,7 @@ const proxyRequest = async (
|
||||
}
|
||||
|
||||
const upstreamResponse = await fetchImpl(targetUrl, requestInit)
|
||||
const responseHeaders = createUpstreamResponseHeaders(
|
||||
upstreamResponse,
|
||||
context.req.header('origin'),
|
||||
requestUrl.protocol === 'https:',
|
||||
)
|
||||
const responseHeaders = createUpstreamResponseHeaders(upstreamResponse, context.req.header('origin'))
|
||||
|
||||
return new Response(upstreamResponse.body, {
|
||||
status: upstreamResponse.status,
|
||||
|
||||
13
web/pnpm-lock.yaml
generated
13
web/pnpm-lock.yaml
generated
@@ -512,9 +512,6 @@ importers:
|
||||
'@typescript/native-preview':
|
||||
specifier: 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':
|
||||
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))
|
||||
@@ -3606,12 +3603,6 @@ packages:
|
||||
resolution: {integrity: sha512-hBcWIOppZV14bi+eAmCZj8Elj8hVSUZJTpf1lgGBhVD85pervzQ1poM/qYfFUlPraYSZYP+ASg6To5BwYmUSGQ==}
|
||||
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':
|
||||
resolution: {integrity: sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
@@ -11039,10 +11030,6 @@ snapshots:
|
||||
'@resvg/resvg-wasm': 2.4.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))':
|
||||
dependencies:
|
||||
'@babel/core': 7.29.0
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import { createSecureServer } from 'node:http2'
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { serve } from '@hono/node-server'
|
||||
import { getCertificate } from '@vitejs/plugin-basic-ssl'
|
||||
import { loadEnv } from 'vite'
|
||||
import { createDevProxyApp, resolveDevProxyTargets, shouldUseHttpsForDevProxy } from '../plugins/dev-proxy/server'
|
||||
import { createDevProxyApp, resolveDevProxyTargets } from '../plugins/dev-proxy/server'
|
||||
|
||||
const projectRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
|
||||
const mode = process.env.MODE || process.env.NODE_ENV || 'development'
|
||||
@@ -13,33 +11,11 @@ const env = loadEnv(mode, projectRoot, '')
|
||||
const host = env.HONO_PROXY_HOST || '127.0.0.1'
|
||||
const port = Number(env.HONO_PROXY_PORT || 5001)
|
||||
const app = createDevProxyApp(resolveDevProxyTargets(env))
|
||||
const useHttps = shouldUseHttpsForDevProxy(env)
|
||||
|
||||
if (useHttps) {
|
||||
const certificate = await getCertificate(
|
||||
path.join(projectRoot, 'node_modules/.vite/basic-ssl'),
|
||||
'localhost',
|
||||
Array.from(new Set(['localhost', '127.0.0.1', host])),
|
||||
)
|
||||
serve({
|
||||
fetch: app.fetch,
|
||||
hostname: 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}`)
|
||||
console.log(`[dev-hono-proxy] listening on http://${host}:${port}`)
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import basicSsl from '@vitejs/plugin-basic-ssl'
|
||||
import react from '@vitejs/plugin-react'
|
||||
import vinext from 'vinext'
|
||||
import { loadEnv } from 'vite'
|
||||
import Inspect from 'vite-plugin-inspect'
|
||||
import { defineConfig } from 'vite-plus'
|
||||
import { shouldUseHttpsForDevProxy } from './plugins/dev-proxy/protocol'
|
||||
import { createCodeInspectorPlugin, createForceInspectorClientInjectionPlugin } from './plugins/vite/code-inspector'
|
||||
import { customI18nHmrPlugin } from './plugins/vite/custom-i18n-hmr'
|
||||
import { nextStaticImageTestPlugin } from './plugins/vite/next-static-image-test'
|
||||
@@ -24,8 +21,6 @@ export default defineConfig(({ mode }) => {
|
||||
const isTest = mode === 'test'
|
||||
const isStorybook = process.env.STORYBOOK === 'true'
|
||||
|| process.argv.some(arg => arg.toLowerCase().includes('storybook'))
|
||||
const env = loadEnv(mode, projectRoot, '')
|
||||
const useHttpsForDevServer = shouldUseHttpsForDevProxy(env)
|
||||
const isAppComponentsCoverage = coverageScope === 'app-components'
|
||||
const excludedComponentCoverageFiles = isAppComponentsCoverage
|
||||
? collectComponentCoverageExcludedFiles(path.join(projectRoot, 'app/components'), { pathPrefix: 'app/components' })
|
||||
@@ -62,7 +57,6 @@ export default defineConfig(({ mode }) => {
|
||||
react(),
|
||||
vinext({ react: false }),
|
||||
customI18nHmrPlugin({ injectTarget: browserInitializerInjectTarget }),
|
||||
...(useHttpsForDevServer ? [basicSsl()] : []),
|
||||
// reactGrabOpenFilePlugin({
|
||||
// injectTarget: browserInitializerInjectTarget,
|
||||
// projectRoot,
|
||||
|
||||
Reference in New Issue
Block a user