Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
赵月辉
/
fastgpt-migrated
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Unverified
Commit
8d67db1e
authored
Apr 29, 2026
by
Archer
Committed by
GitHub
Apr 29, 2026
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: stt usage (#6855)
* fix: stt usage * perf: skil ssrf with some api * fix:test
parent
073bd591
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
27 additions
and
97 deletions
+27
-97
packages/service/common/api/axios.ts
+1
-0
packages/service/core/ai/audio/transcriptions.ts
+8
-11
packages/service/core/ai/rerank/index.ts
+3
-2
packages/service/core/workflow/dispatch/tools/http468.ts
+1
-2
packages/service/core/workflow/dispatch/tools/runLaf.ts
+0
-2
packages/service/test/core/ai/rerank/index.test.ts
+2
-2
packages/service/thirdProvider/codeSandbox/index.ts
+6
-3
packages/service/thirdProvider/textin/index.ts
+2
-2
projects/app/src/pages/api/aiproxy/api/createChannel.ts
+2
-2
projects/app/src/service/core/ai/apiproxy.ts
+0
-68
projects/app/src/service/support/wallet/usage/push.ts
+2
-3
No files found.
packages/service/common/api/axios.ts
View file @
8d67db1e
...
@@ -43,6 +43,7 @@ export function createProxyAxios(config?: AxiosRequestConfig, ssrfCheck = true)
...
@@ -43,6 +43,7 @@ export function createProxyAxios(config?: AxiosRequestConfig, ssrfCheck = true)
/** @see https://github.com/axios/axios/issues/4531 */
/** @see https://github.com/axios/axios/issues/4531 */
export
const
axios
=
createProxyAxios
();
export
const
axios
=
createProxyAxios
();
export
const
axiosWithoutSSRF
=
createProxyAxios
(
undefined
,
false
);
/**
/**
* 内部相对路径请求专用的 axios 实例:
* 内部相对路径请求专用的 axios 实例:
...
...
packages/service/core/ai/audio/transcriptions.ts
View file @
8d67db1e
import
type
fs
from
'fs'
;
import
type
fs
from
'fs'
;
import
{
getAxiosConfig
}
from
'../config'
;
import
{
getAxiosConfig
}
from
'../config'
;
import
{
axios
}
from
'../../../common/api/axios'
;
import
{
axios
WithoutSSRF
}
from
'../../../common/api/axios'
;
import
FormData
from
'form-data'
;
import
FormData
from
'form-data'
;
import
{
type
STTModelType
}
from
'@fastgpt/global/core/ai/model.schema'
;
import
{
type
STTModelType
}
from
'@fastgpt/global/core/ai/model.schema'
;
import
{
UserError
}
from
'@fastgpt/global/common/error/utils'
;
import
{
UserError
}
from
'@fastgpt/global/common/error/utils'
;
...
@@ -24,22 +24,19 @@ export const aiTranscriptions = async ({
...
@@ -24,22 +24,19 @@ export const aiTranscriptions = async ({
const
aiAxiosConfig
=
getAxiosConfig
();
const
aiAxiosConfig
=
getAxiosConfig
();
const
{
data
:
result
}
=
await
axios
<
{
text
:
string
;
usage
?:
{
total_tokens
:
number
}
}
>
({
// 管理员配置的 url,允许是内网
method
:
'post'
,
const
{
data
:
result
}
=
await
axiosWithoutSSRF
.
post
<
{
...(
modelData
.
requestUrl
text
:
string
;
?
{
url
:
modelData
.
requestUrl
}
usage
?:
{
total_tokens
:
number
};
:
{
}
>
(
modelData
.
requestUrl
?
modelData
.
requestUrl
:
'/audio/transcriptions'
,
data
,
{
baseURL
:
aiAxiosConfig
.
baseUrl
,
...(
modelData
.
requestUrl
?
{}
:
{
baseURL
:
aiAxiosConfig
.
baseUrl
}),
url
:
'/audio/transcriptions'
}),
headers
:
{
headers
:
{
Authorization
:
modelData
.
requestAuth
Authorization
:
modelData
.
requestAuth
?
`Bearer
${
modelData
.
requestAuth
}
`
?
`Bearer
${
modelData
.
requestAuth
}
`
:
aiAxiosConfig
.
authorization
,
:
aiAxiosConfig
.
authorization
,
...
data
.
getHeaders
(),
...
data
.
getHeaders
(),
...
headers
...
headers
},
}
data
:
data
});
});
return
result
;
return
result
;
...
...
packages/service/core/ai/rerank/index.ts
View file @
8d67db1e
import
{
axios
}
from
'../../../common/api/axios'
;
import
{
axios
WithoutSSRF
}
from
'../../../common/api/axios'
;
import
{
getDefaultRerankModel
}
from
'../model'
;
import
{
getDefaultRerankModel
}
from
'../model'
;
import
{
getAxiosConfig
}
from
'../config'
;
import
{
getAxiosConfig
}
from
'../config'
;
import
{
type
RerankModelItemType
}
from
'@fastgpt/global/core/ai/model.schema'
;
import
{
type
RerankModelItemType
}
from
'@fastgpt/global/core/ai/model.schema'
;
...
@@ -93,8 +93,9 @@ export async function reRankRecall({
...
@@ -93,8 +93,9 @@ export async function reRankRecall({
const
{
baseUrl
,
authorization
}
=
getAxiosConfig
();
const
{
baseUrl
,
authorization
}
=
getAxiosConfig
();
const
start
=
Date
.
now
();
const
start
=
Date
.
now
();
// 模型的请求 url,允许是内网
const
requestUrl
=
model
.
requestUrl
?
model
.
requestUrl
:
`
${
baseUrl
}
/rerank`
;
const
requestUrl
=
model
.
requestUrl
?
model
.
requestUrl
:
`
${
baseUrl
}
/rerank`
;
const
apiResult
=
await
axios
const
apiResult
=
await
axios
WithoutSSRF
.
post
<
PostReRankResponse
>
(
.
post
<
PostReRankResponse
>
(
requestUrl
,
requestUrl
,
{
{
...
...
packages/service/core/workflow/dispatch/tools/http468.ts
View file @
8d67db1e
...
@@ -24,7 +24,6 @@ import { JSONPath } from 'jsonpath-plus';
...
@@ -24,7 +24,6 @@ import { JSONPath } from 'jsonpath-plus';
import
{
getSecretValue
}
from
'../../../../common/secret/utils'
;
import
{
getSecretValue
}
from
'../../../../common/secret/utils'
;
import
type
{
StoreSecretValueType
}
from
'@fastgpt/global/common/secret/type'
;
import
type
{
StoreSecretValueType
}
from
'@fastgpt/global/common/secret/type'
;
import
{
getLogger
,
LogCategories
}
from
'../../../../common/logger'
;
import
{
getLogger
,
LogCategories
}
from
'../../../../common/logger'
;
import
{
SERVICE_LOCAL_HOST
}
from
'../../../../common/system/tools'
;
import
{
formatHttpError
}
from
'../utils'
;
import
{
formatHttpError
}
from
'../utils'
;
import
{
isInternalAddress
,
PRIVATE_URL_TEXT
}
from
'../../../../common/system/utils'
;
import
{
isInternalAddress
,
PRIVATE_URL_TEXT
}
from
'../../../../common/system/utils'
;
import
{
serviceRequestMaxContentLength
}
from
'../../../../common/system/constants'
;
import
{
serviceRequestMaxContentLength
}
from
'../../../../common/system/constants'
;
...
@@ -504,10 +503,10 @@ async function fetchData({
...
@@ -504,10 +503,10 @@ async function fetchData({
return
Promise
.
reject
(
PRIVATE_URL_TEXT
);
return
Promise
.
reject
(
PRIVATE_URL_TEXT
);
}
}
// 都认为是用户的请求,强制 SSRF 检查
const
{
data
:
response
}
=
await
axios
({
const
{
data
:
response
}
=
await
axios
({
method
,
method
,
maxContentLength
:
serviceRequestMaxContentLength
,
maxContentLength
:
serviceRequestMaxContentLength
,
baseURL
:
`http://
${
SERVICE_LOCAL_HOST
}
`
,
url
,
url
,
headers
:
{
headers
:
{
...
headers
...
headers
...
...
packages/service/core/workflow/dispatch/tools/runLaf.ts
View file @
8d67db1e
...
@@ -3,7 +3,6 @@ import { NodeInputKeyEnum, NodeOutputKeyEnum } from '@fastgpt/global/core/workfl
...
@@ -3,7 +3,6 @@ import { NodeInputKeyEnum, NodeOutputKeyEnum } from '@fastgpt/global/core/workfl
import
{
DispatchNodeResponseKeyEnum
}
from
'@fastgpt/global/core/workflow/runtime/constants'
;
import
{
DispatchNodeResponseKeyEnum
}
from
'@fastgpt/global/core/workflow/runtime/constants'
;
import
{
axios
}
from
'../../../../common/api/axios'
;
import
{
axios
}
from
'../../../../common/api/axios'
;
import
{
valueTypeFormat
}
from
'@fastgpt/global/core/workflow/runtime/utils'
;
import
{
valueTypeFormat
}
from
'@fastgpt/global/core/workflow/runtime/utils'
;
import
{
SERVICE_LOCAL_HOST
}
from
'../../../../common/system/tools'
;
import
{
type
DispatchNodeResultType
}
from
'@fastgpt/global/core/workflow/runtime/type'
;
import
{
type
DispatchNodeResultType
}
from
'@fastgpt/global/core/workflow/runtime/type'
;
import
{
getErrText
}
from
'@fastgpt/global/common/error/utils'
;
import
{
getErrText
}
from
'@fastgpt/global/common/error/utils'
;
import
{
getLogger
,
LogCategories
}
from
'../../../../common/logger'
;
import
{
getLogger
,
LogCategories
}
from
'../../../../common/logger'
;
...
@@ -122,7 +121,6 @@ async function fetchData({
...
@@ -122,7 +121,6 @@ async function fetchData({
}):
Promise
<
Record
<
string
,
any
>>
{
}):
Promise
<
Record
<
string
,
any
>>
{
const
{
data
:
response
}
=
await
axios
({
const
{
data
:
response
}
=
await
axios
({
method
,
method
,
baseURL
:
`http://
${
SERVICE_LOCAL_HOST
}
`
,
url
,
url
,
headers
:
{
headers
:
{
'Content-Type'
:
'application/json'
'Content-Type'
:
'application/json'
...
...
packages/service/test/core/ai/rerank/index.test.ts
View file @
8d67db1e
...
@@ -13,9 +13,9 @@ vi.mock('@fastgpt/service/common/string/tiktoken', () => ({
...
@@ -13,9 +13,9 @@ vi.mock('@fastgpt/service/common/string/tiktoken', () => ({
countPromptTokens
:
mockCountPromptTokens
countPromptTokens
:
mockCountPromptTokens
}));
}));
// rerank
现在改用统一 axios(带 SSRF 拦截),mock axios
.post 返回 axios 风格的 { data, ... }
// rerank
走 axiosWithoutSSRF(管理员配置的 url 允许内网),mock 它的
.post 返回 axios 风格的 { data, ... }
vi
.
mock
(
'@fastgpt/service/common/api/axios'
,
()
=>
({
vi
.
mock
(
'@fastgpt/service/common/api/axios'
,
()
=>
({
axios
:
{
axios
WithoutSSRF
:
{
post
:
(...
args
:
any
[])
=>
Promise
.
resolve
(
mockAxiosPost
(...
args
)).
then
((
data
)
=>
({
data
}))
post
:
(...
args
:
any
[])
=>
Promise
.
resolve
(
mockAxiosPost
(...
args
)).
then
((
data
)
=>
({
data
}))
}
}
}));
}));
...
...
packages/service/thirdProvider/codeSandbox/index.ts
View file @
8d67db1e
import
{
SandboxCodeTypeEnum
}
from
'@fastgpt/global/core/workflow/template/system/sandbox/constants'
;
import
{
SandboxCodeTypeEnum
}
from
'@fastgpt/global/core/workflow/template/system/sandbox/constants'
;
import
type
{
AxiosInstance
}
from
'axios'
;
import
type
{
AxiosInstance
}
from
'axios'
;
import
axios
from
'
axios'
;
import
{
createProxyAxios
}
from
'../../common/api/
axios'
;
import
{
getLogger
,
LogCategories
}
from
'../../common/logger'
;
import
{
getLogger
,
LogCategories
}
from
'../../common/logger'
;
const
logger
=
getLogger
(
LogCategories
.
MODULE
.
WORKFLOW
.
CODE_SANDBOX
);
const
logger
=
getLogger
(
LogCategories
.
MODULE
.
WORKFLOW
.
CODE_SANDBOX
);
...
@@ -17,14 +17,17 @@ export class CodeSandbox {
...
@@ -17,14 +17,17 @@ export class CodeSandbox {
const
baseUrl
=
process
.
env
.
CODE_SANDBOX_URL
||
''
;
const
baseUrl
=
process
.
env
.
CODE_SANDBOX_URL
||
''
;
const
token
=
process
.
env
.
CODE_SANDBOX_TOKEN
||
''
;
const
token
=
process
.
env
.
CODE_SANDBOX_TOKEN
||
''
;
this
.
client
=
axios
.
create
({
this
.
client
=
createProxyAxios
(
{
baseURL
:
`
${
baseUrl
.
replace
(
/
\/
$/
,
''
)}
/sandbox`
,
baseURL
:
`
${
baseUrl
.
replace
(
/
\/
$/
,
''
)}
/sandbox`
,
timeout
:
180000
,
timeout
:
180000
,
headers
:
{
headers
:
{
'Content-Type'
:
'application/json'
,
'Content-Type'
:
'application/json'
,
Authorization
:
token
?
`Bearer
${
token
}
`
:
undefined
Authorization
:
token
?
`Bearer
${
token
}
`
:
undefined
}
}
});
},
false
);
this
.
client
.
interceptors
.
response
.
use
(
this
.
client
.
interceptors
.
response
.
use
(
(
response
)
=>
{
(
response
)
=>
{
...
...
packages/service/thirdProvider/textin/index.ts
View file @
8d67db1e
import
{
matchMdImg
}
from
'@fastgpt/global/common/string/markdown'
;
import
{
matchMdImg
}
from
'@fastgpt/global/common/string/markdown'
;
import
axios
from
'
axios'
;
import
{
createProxyAxios
}
from
'../../common/api/
axios'
;
import
{
getErrText
}
from
'@fastgpt/global/common/error/utils'
;
import
{
getErrText
}
from
'@fastgpt/global/common/error/utils'
;
import
{
getLogger
,
LogCategories
}
from
'../../common/logger'
;
import
{
getLogger
,
LogCategories
}
from
'../../common/logger'
;
export
const
useTextinServer
=
({
appId
,
secretCode
}:
{
appId
:
string
;
secretCode
:
string
})
=>
{
export
const
useTextinServer
=
({
appId
,
secretCode
}:
{
appId
:
string
;
secretCode
:
string
})
=>
{
const
logger
=
getLogger
(
LogCategories
.
MODULE
.
DATASET
.
FILE
);
const
logger
=
getLogger
(
LogCategories
.
MODULE
.
DATASET
.
FILE
);
// Init request
// Init request
const
instance
=
axios
.
create
({
const
instance
=
createProxyAxios
({
baseURL
:
'https://api.textin.com/ai/service/v1'
,
baseURL
:
'https://api.textin.com/ai/service/v1'
,
timeout
:
300000
,
timeout
:
300000
,
headers
:
{
headers
:
{
...
...
projects/app/src/pages/api/aiproxy/api/createChannel.ts
View file @
8d67db1e
import
type
{
ApiRequestProps
,
ApiResponseType
}
from
'@fastgpt/service/type/next'
;
import
type
{
ApiRequestProps
,
ApiResponseType
}
from
'@fastgpt/service/type/next'
;
import
{
authSystemAdmin
}
from
'@fastgpt/service/support/permission/user/auth'
;
import
{
authSystemAdmin
}
from
'@fastgpt/service/support/permission/user/auth'
;
import
{
axios
}
from
'@fastgpt/service/common/api/axios'
;
import
{
axios
WithoutSSRF
}
from
'@fastgpt/service/common/api/axios'
;
import
{
getErrText
}
from
'@fastgpt/global/common/error/utils'
;
import
{
getErrText
}
from
'@fastgpt/global/common/error/utils'
;
const
baseUrl
=
process
.
env
.
AIPROXY_API_ENDPOINT
;
const
baseUrl
=
process
.
env
.
AIPROXY_API_ENDPOINT
;
...
@@ -14,7 +14,7 @@ async function handler(req: ApiRequestProps, res: ApiResponseType<any>) {
...
@@ -14,7 +14,7 @@ async function handler(req: ApiRequestProps, res: ApiResponseType<any>) {
return
Promise
.
reject
(
'AIPROXY_API_ENDPOINT or AIPROXY_API_TOKEN is not set'
);
return
Promise
.
reject
(
'AIPROXY_API_ENDPOINT or AIPROXY_API_TOKEN is not set'
);
}
}
const
{
data
}
=
await
axios
.
post
(
`
${
baseUrl
}
/api/channel/`
,
req
.
body
,
{
const
{
data
}
=
await
axios
WithoutSSRF
.
post
(
`
${
baseUrl
}
/api/channel/`
,
req
.
body
,
{
headers
:
{
headers
:
{
Authorization
:
`Bearer
${
token
}
`
Authorization
:
`Bearer
${
token
}
`
}
}
...
...
projects/app/src/service/core/ai/apiproxy.ts
deleted
100644 → 0
View file @
073bd591
import
{
getLogger
,
LogCategories
}
from
'@fastgpt/service/common/logger'
;
import
{
type
Method
}
from
'axios'
;
import
{
createProxyAxios
}
from
'@fastgpt/service/common/api/axios'
;
const
logger
=
getLogger
(
LogCategories
.
NETWORK
);
const
url
=
process
.
env
.
API_PROXY_URL
;
const
token
=
process
.
env
.
API_PROXY_TOKEN
;
const
instance
=
createProxyAxios
({
baseURL
:
url
,
timeout
:
60000
,
// 超时时间
headers
:
{
Authorization
:
`Bearer
${
token
}
`
}
});
/**
* 响应数据检查
*/
const
checkRes
=
(
data
:
any
)
=>
{
if
(
data
===
undefined
)
{
logger
.
info
(
'api proxy data is empty'
);
return
Promise
.
reject
(
'服务器异常'
);
}
return
data
.
data
;
};
const
responseError
=
(
err
:
any
)
=>
{
logger
.
error
(
'API proxy request failed'
,
{
error
:
err
});
if
(
!
err
)
{
return
Promise
.
reject
({
message
:
'未知错误'
});
}
if
(
typeof
err
===
'string'
)
{
return
Promise
.
reject
({
message
:
err
});
}
if
(
typeof
err
.
message
===
'string'
)
{
return
Promise
.
reject
({
message
:
err
.
message
});
}
if
(
typeof
err
.
data
===
'string'
)
{
return
Promise
.
reject
({
message
:
err
.
data
});
}
if
(
err
?.
response
?.
data
)
{
return
Promise
.
reject
(
err
?.
response
?.
data
);
}
return
Promise
.
reject
(
err
);
};
const
request
=
<
T
>
(
url
:
string
,
data
:
any
,
method
:
Method
):
Promise
<
T
>
=>
{
/* 去空 */
for
(
const
key
in
data
)
{
if
(
data
[
key
]
===
undefined
)
{
delete
data
[
key
];
}
}
return
instance
.
request
({
url
,
method
,
data
:
[
'POST'
,
'PUT'
].
includes
(
method
)
?
data
:
undefined
,
params
:
!
[
'POST'
,
'PUT'
].
includes
(
method
)
?
data
:
undefined
})
.
then
((
res
)
=>
checkRes
(
res
.
data
))
.
catch
((
err
)
=>
responseError
(
err
));
};
// TODO: channel crud
export
const
ApiProxy
=
{};
projects/app/src/service/support/wallet/usage/push.ts
View file @
8d67db1e
...
@@ -2,9 +2,8 @@ import { UsageItemTypeEnum, UsageSourceEnum } from '@fastgpt/global/support/wall
...
@@ -2,9 +2,8 @@ import { UsageItemTypeEnum, UsageSourceEnum } from '@fastgpt/global/support/wall
import
{
createUsage
,
concatUsage
}
from
'@fastgpt/service/support/wallet/usage/controller'
;
import
{
createUsage
,
concatUsage
}
from
'@fastgpt/service/support/wallet/usage/controller'
;
import
{
formatModelChars2Points
}
from
'@fastgpt/service/support/wallet/usage/utils'
;
import
{
formatModelChars2Points
}
from
'@fastgpt/service/support/wallet/usage/utils'
;
import
{
i18nT
}
from
'@fastgpt/web/i18n/utils'
;
import
{
i18nT
}
from
'@fastgpt/web/i18n/utils'
;
import
{
getDefault
TTS
Model
}
from
'@fastgpt/service/core/ai/model'
;
import
{
getDefault
STT
Model
}
from
'@fastgpt/service/core/ai/model'
;
import
type
{
UsageItemType
}
from
'@fastgpt/global/support/wallet/usage/type'
;
import
type
{
UsageItemType
}
from
'@fastgpt/global/support/wallet/usage/type'
;
import
type
{
HelperBotTypeEnumType
}
from
'@fastgpt/global/core/chat/helperBot/type'
;
export
const
pushHelperBotUsage
=
({
export
const
pushHelperBotUsage
=
({
teamId
,
teamId
,
...
@@ -246,7 +245,7 @@ export const pushWhisperUsage = ({
...
@@ -246,7 +245,7 @@ export const pushWhisperUsage = ({
tmbId
:
string
;
tmbId
:
string
;
duration
:
number
;
duration
:
number
;
})
=>
{
})
=>
{
const
whisperModel
=
getDefault
TTS
Model
();
const
whisperModel
=
getDefault
STT
Model
();
if
(
!
whisperModel
)
return
;
if
(
!
whisperModel
)
return
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment