@raiseinfo/smartorder-stdio-mcp 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/tools/file-upload.js +45 -14
- package/dist/utils/http-client.d.ts +8 -5
- package/dist/utils/http-client.js +82 -55
- package/package.json +1 -1
- package/src/tools/file-upload.ts +45 -15
- package/src/utils/http-client.ts +97 -60
|
@@ -42,33 +42,63 @@ export async function handleUpload(args) {
|
|
|
42
42
|
await fileReader.validate(file_path);
|
|
43
43
|
let apiUrl;
|
|
44
44
|
let cache = await cacheManager.load();
|
|
45
|
+
const baseUrl = process.env.SMARTORDER_API_BASE || 'https://smart-order.raiseinfo.cn';
|
|
45
46
|
if (cache && !cacheManager.isExpired(cache)) {
|
|
47
|
+
console.log('[Upload] Using cached config');
|
|
46
48
|
apiUrl = cache.apiUrl;
|
|
47
49
|
}
|
|
48
50
|
else {
|
|
49
51
|
try {
|
|
52
|
+
console.log('[Upload] Fetching new config from backend...');
|
|
50
53
|
const config = await httpClient.getConfig();
|
|
51
|
-
|
|
54
|
+
if (config?.data?.apiUrl) {
|
|
55
|
+
apiUrl = config.data.apiUrl;
|
|
56
|
+
console.log('[Upload] Got config from backend:', apiUrl);
|
|
57
|
+
await cacheManager.save({
|
|
58
|
+
version: 1,
|
|
59
|
+
apiUrl: config.data.apiUrl,
|
|
60
|
+
folder: config.data.folder,
|
|
61
|
+
prefix: config.data.prefix,
|
|
62
|
+
tenantCode: process.env.TENANT_CODE || '',
|
|
63
|
+
expiresIn: config.data.expiresIn,
|
|
64
|
+
obtainedAt: Date.now(),
|
|
65
|
+
expiresAt: Date.now() + config.data.expiresIn * 1000,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
console.log('[Upload] Backend config invalid, using fallback');
|
|
70
|
+
apiUrl = baseUrl + '/api/mcp/upload';
|
|
71
|
+
await cacheManager.save({
|
|
72
|
+
version: 1,
|
|
73
|
+
apiUrl: apiUrl,
|
|
74
|
+
folder: 'smart-order/',
|
|
75
|
+
prefix: 'smart-order/',
|
|
76
|
+
tenantCode: process.env.TENANT_CODE || '',
|
|
77
|
+
expiresIn: 28800,
|
|
78
|
+
obtainedAt: Date.now(),
|
|
79
|
+
expiresAt: Date.now() + 28800 * 1000,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
console.log('[Upload] Failed to get config, using fallback URL');
|
|
85
|
+
console.log('[Upload] Error:', error.message);
|
|
86
|
+
apiUrl = baseUrl + '/api/mcp/upload';
|
|
52
87
|
await cacheManager.save({
|
|
53
88
|
version: 1,
|
|
54
|
-
apiUrl:
|
|
55
|
-
folder:
|
|
56
|
-
prefix:
|
|
89
|
+
apiUrl: apiUrl,
|
|
90
|
+
folder: 'smart-order/',
|
|
91
|
+
prefix: 'smart-order/',
|
|
57
92
|
tenantCode: process.env.TENANT_CODE || '',
|
|
58
|
-
expiresIn:
|
|
93
|
+
expiresIn: 28800,
|
|
59
94
|
obtainedAt: Date.now(),
|
|
60
|
-
expiresAt: Date.now() +
|
|
95
|
+
expiresAt: Date.now() + 28800 * 1000,
|
|
61
96
|
});
|
|
62
97
|
}
|
|
63
|
-
catch (error) {
|
|
64
|
-
return {
|
|
65
|
-
content: [{ type: 'text', text: `获取配置失败:${error.message}` }],
|
|
66
|
-
isError: true,
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
98
|
}
|
|
70
99
|
try {
|
|
71
|
-
|
|
100
|
+
console.log('[Upload] Uploading to:', apiUrl);
|
|
101
|
+
const result = await httpClient.uploadFile(file_path, folder, apiUrl);
|
|
72
102
|
return {
|
|
73
103
|
content: [
|
|
74
104
|
{
|
|
@@ -87,7 +117,8 @@ export async function handleUpload(args) {
|
|
|
87
117
|
}
|
|
88
118
|
if (error.message.includes('5xx') || error.message.includes('网络')) {
|
|
89
119
|
try {
|
|
90
|
-
|
|
120
|
+
console.log('[Upload] Retrying upload...');
|
|
121
|
+
const result = await httpClient.uploadFile(file_path, folder, apiUrl);
|
|
91
122
|
return {
|
|
92
123
|
content: [{ type: 'text', text: JSON.stringify(result.data, null, 2) }],
|
|
93
124
|
};
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { McpConfigResponse, McpUploadResponse } from '../types/index.js';
|
|
2
2
|
export declare class HttpClient {
|
|
3
|
-
private baseUrl;
|
|
4
|
-
private tenantCode;
|
|
5
|
-
private mcpToken;
|
|
6
|
-
|
|
3
|
+
private get baseUrl();
|
|
4
|
+
private get tenantCode();
|
|
5
|
+
private get mcpToken();
|
|
6
|
+
private get authHeaders();
|
|
7
7
|
getConfig(): Promise<McpConfigResponse>;
|
|
8
|
-
uploadFile(filePath: string, folder: string): Promise<McpUploadResponse>;
|
|
8
|
+
uploadFile(filePath: string, folder: string, apiUrl?: string): Promise<McpUploadResponse>;
|
|
9
|
+
private uploadWithRetry;
|
|
10
|
+
private doUpload;
|
|
9
11
|
private request;
|
|
12
|
+
private handleResponse;
|
|
10
13
|
}
|
|
@@ -3,79 +3,106 @@ import path from 'path';
|
|
|
3
3
|
import FormData from 'form-data';
|
|
4
4
|
import http from 'http';
|
|
5
5
|
import https from 'https';
|
|
6
|
+
const MAX_RETRIES = 2;
|
|
6
7
|
export class HttpClient {
|
|
7
|
-
baseUrl
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
get baseUrl() {
|
|
9
|
+
return process.env.SMARTORDER_API_BASE || 'https://smart-order.raiseinfo.cn';
|
|
10
|
+
}
|
|
11
|
+
get tenantCode() {
|
|
12
|
+
return process.env.TENANT_CODE || '';
|
|
13
|
+
}
|
|
14
|
+
get mcpToken() {
|
|
15
|
+
return process.env.MCP_TOKEN || '';
|
|
16
|
+
}
|
|
17
|
+
get authHeaders() {
|
|
18
|
+
return {
|
|
19
|
+
'X-Tenant-Code': this.tenantCode,
|
|
20
|
+
'X-Mcp-Token': this.mcpToken,
|
|
21
|
+
};
|
|
14
22
|
}
|
|
15
23
|
async getConfig() {
|
|
16
24
|
const url = `${this.baseUrl}/api/mcp/config`;
|
|
25
|
+
console.log('[HTTP] GET', url);
|
|
17
26
|
return this.request('GET', url);
|
|
18
27
|
}
|
|
19
|
-
async uploadFile(filePath, folder) {
|
|
20
|
-
const url = `${this.baseUrl}/api/mcp/upload`;
|
|
21
|
-
|
|
22
|
-
const fileStream = fs.createReadStream(filePath);
|
|
23
|
-
const fileName = path.basename(filePath);
|
|
24
|
-
form.append('file', fileStream, { filename: fileName });
|
|
25
|
-
form.append('folder', folder);
|
|
26
|
-
return this.request('POST', url, form, true);
|
|
28
|
+
async uploadFile(filePath, folder, apiUrl) {
|
|
29
|
+
const url = apiUrl || `${this.baseUrl}/api/mcp/upload`;
|
|
30
|
+
return this.uploadWithRetry(filePath, folder, url);
|
|
27
31
|
}
|
|
28
|
-
|
|
32
|
+
async uploadWithRetry(filePath, folder, url, attempt = 1) {
|
|
33
|
+
console.log(`[HTTP] Upload attempt ${attempt}/${MAX_RETRIES + 1}:`, filePath);
|
|
34
|
+
try {
|
|
35
|
+
return await this.doUpload(filePath, folder, url);
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
console.error(`[HTTP] Upload attempt ${attempt} failed:`, error.message);
|
|
39
|
+
if (attempt <= MAX_RETRIES) {
|
|
40
|
+
console.log(`[HTTP] Retrying... (${attempt + 1}/${MAX_RETRIES + 1})`);
|
|
41
|
+
return this.uploadWithRetry(filePath, folder, url, attempt + 1);
|
|
42
|
+
}
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
doUpload(filePath, folder, url) {
|
|
29
47
|
return new Promise((resolve, reject) => {
|
|
48
|
+
const form = new FormData();
|
|
49
|
+
form.append('file', fs.createReadStream(filePath), { filename: path.basename(filePath) });
|
|
50
|
+
form.append('folder', folder);
|
|
30
51
|
const urlObj = new URL(url);
|
|
31
52
|
const client = urlObj.protocol === 'https:' ? https : http;
|
|
32
|
-
const
|
|
53
|
+
const req = client.request({
|
|
54
|
+
hostname: urlObj.hostname,
|
|
55
|
+
port: urlObj.port || (urlObj.protocol === 'https:' ? 443 : 80),
|
|
56
|
+
path: urlObj.pathname,
|
|
57
|
+
method: 'POST',
|
|
58
|
+
headers: { ...this.authHeaders, ...form.getHeaders() },
|
|
59
|
+
});
|
|
60
|
+
this.handleResponse(req, resolve, reject);
|
|
61
|
+
req.on('error', (err) => reject(new Error(`网络错误:${err.message}`)));
|
|
62
|
+
form.pipe(req);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
request(method, url) {
|
|
66
|
+
return new Promise((resolve, reject) => {
|
|
67
|
+
const urlObj = new URL(url);
|
|
68
|
+
const client = urlObj.protocol === 'https:' ? https : http;
|
|
69
|
+
const req = client.request({
|
|
33
70
|
hostname: urlObj.hostname,
|
|
34
71
|
port: urlObj.port || (urlObj.protocol === 'https:' ? 443 : 80),
|
|
35
72
|
path: urlObj.pathname,
|
|
36
73
|
method,
|
|
37
|
-
headers: {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
else if (res.statusCode === 404) {
|
|
56
|
-
reject(new Error('上传服务路径不存在,请联系管理员'));
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
reject(new Error(`服务返回错误:${res.statusCode}`));
|
|
60
|
-
}
|
|
74
|
+
headers: { ...this.authHeaders, 'Content-Type': 'application/json' },
|
|
75
|
+
});
|
|
76
|
+
this.handleResponse(req, resolve, reject);
|
|
77
|
+
req.on('error', (err) => reject(new Error(`网络错误:${err.message}`)));
|
|
78
|
+
req.end();
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
handleResponse(req, resolve, reject) {
|
|
82
|
+
req.on('response', (res) => {
|
|
83
|
+
let data = '';
|
|
84
|
+
res.on('data', (chunk) => (data += chunk));
|
|
85
|
+
res.on('end', () => {
|
|
86
|
+
console.log('[HTTP] Response:', res.statusCode, data.substring(0, 200));
|
|
87
|
+
try {
|
|
88
|
+
const json = JSON.parse(data);
|
|
89
|
+
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
|
|
90
|
+
resolve(json);
|
|
61
91
|
}
|
|
62
|
-
|
|
63
|
-
reject(new Error('
|
|
92
|
+
else if (res.statusCode === 401 || res.statusCode === 403) {
|
|
93
|
+
reject(new Error('认证失败,请检查租户Token配置'));
|
|
94
|
+
}
|
|
95
|
+
else if (res.statusCode === 404) {
|
|
96
|
+
reject(new Error('上传服务路径不存在,请联系管理员'));
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
reject(new Error(`服务返回错误:${res.statusCode}`));
|
|
64
100
|
}
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
req.on('error', (err) => {
|
|
68
|
-
reject(new Error(`网络错误:${err.message}`));
|
|
69
|
-
});
|
|
70
|
-
if (body) {
|
|
71
|
-
if (isFormData) {
|
|
72
|
-
body.pipe(req);
|
|
73
101
|
}
|
|
74
|
-
|
|
75
|
-
|
|
102
|
+
catch (e) {
|
|
103
|
+
reject(new Error('响应解析失败: ' + data.substring(0, 100)));
|
|
76
104
|
}
|
|
77
|
-
}
|
|
78
|
-
req.end();
|
|
105
|
+
});
|
|
79
106
|
});
|
|
80
107
|
}
|
|
81
108
|
}
|
package/package.json
CHANGED
package/src/tools/file-upload.ts
CHANGED
|
@@ -49,34 +49,63 @@ export async function handleUpload(args: { file_path: string; folder?: string })
|
|
|
49
49
|
|
|
50
50
|
let apiUrl: string;
|
|
51
51
|
let cache = await cacheManager.load();
|
|
52
|
+
const baseUrl = process.env.SMARTORDER_API_BASE || 'https://smart-order.raiseinfo.cn';
|
|
52
53
|
|
|
53
54
|
if (cache && !cacheManager.isExpired(cache)) {
|
|
55
|
+
console.log('[Upload] Using cached config');
|
|
54
56
|
apiUrl = cache.apiUrl;
|
|
55
57
|
} else {
|
|
56
58
|
try {
|
|
59
|
+
console.log('[Upload] Fetching new config from backend...');
|
|
57
60
|
const config = await httpClient.getConfig();
|
|
58
|
-
|
|
59
|
-
|
|
61
|
+
|
|
62
|
+
if (config?.data?.apiUrl) {
|
|
63
|
+
apiUrl = config.data.apiUrl;
|
|
64
|
+
console.log('[Upload] Got config from backend:', apiUrl);
|
|
65
|
+
await cacheManager.save({
|
|
66
|
+
version: 1,
|
|
67
|
+
apiUrl: config.data.apiUrl,
|
|
68
|
+
folder: config.data.folder,
|
|
69
|
+
prefix: config.data.prefix,
|
|
70
|
+
tenantCode: process.env.TENANT_CODE || '',
|
|
71
|
+
expiresIn: config.data.expiresIn,
|
|
72
|
+
obtainedAt: Date.now(),
|
|
73
|
+
expiresAt: Date.now() + config.data.expiresIn * 1000,
|
|
74
|
+
});
|
|
75
|
+
} else {
|
|
76
|
+
console.log('[Upload] Backend config invalid, using fallback');
|
|
77
|
+
apiUrl = baseUrl + '/api/mcp/upload';
|
|
78
|
+
await cacheManager.save({
|
|
79
|
+
version: 1,
|
|
80
|
+
apiUrl: apiUrl,
|
|
81
|
+
folder: 'smart-order/',
|
|
82
|
+
prefix: 'smart-order/',
|
|
83
|
+
tenantCode: process.env.TENANT_CODE || '',
|
|
84
|
+
expiresIn: 28800,
|
|
85
|
+
obtainedAt: Date.now(),
|
|
86
|
+
expiresAt: Date.now() + 28800 * 1000,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
} catch (error: any) {
|
|
90
|
+
console.log('[Upload] Failed to get config, using fallback URL');
|
|
91
|
+
console.log('[Upload] Error:', error.message);
|
|
92
|
+
apiUrl = baseUrl + '/api/mcp/upload';
|
|
60
93
|
await cacheManager.save({
|
|
61
94
|
version: 1,
|
|
62
|
-
apiUrl:
|
|
63
|
-
folder:
|
|
64
|
-
prefix:
|
|
95
|
+
apiUrl: apiUrl,
|
|
96
|
+
folder: 'smart-order/',
|
|
97
|
+
prefix: 'smart-order/',
|
|
65
98
|
tenantCode: process.env.TENANT_CODE || '',
|
|
66
|
-
expiresIn:
|
|
99
|
+
expiresIn: 28800,
|
|
67
100
|
obtainedAt: Date.now(),
|
|
68
|
-
expiresAt: Date.now() +
|
|
101
|
+
expiresAt: Date.now() + 28800 * 1000,
|
|
69
102
|
});
|
|
70
|
-
} catch (error: any) {
|
|
71
|
-
return {
|
|
72
|
-
content: [{ type: 'text', text: `获取配置失败:${error.message}` }],
|
|
73
|
-
isError: true,
|
|
74
|
-
};
|
|
75
103
|
}
|
|
76
104
|
}
|
|
77
105
|
|
|
78
106
|
try {
|
|
79
|
-
|
|
107
|
+
console.log('[Upload] Uploading to:', apiUrl);
|
|
108
|
+
const result = await httpClient.uploadFile(file_path, folder, apiUrl);
|
|
80
109
|
return {
|
|
81
110
|
content: [
|
|
82
111
|
{
|
|
@@ -95,7 +124,8 @@ export async function handleUpload(args: { file_path: string; folder?: string })
|
|
|
95
124
|
|
|
96
125
|
if (error.message.includes('5xx') || error.message.includes('网络')) {
|
|
97
126
|
try {
|
|
98
|
-
|
|
127
|
+
console.log('[Upload] Retrying upload...');
|
|
128
|
+
const result = await httpClient.uploadFile(file_path, folder, apiUrl);
|
|
99
129
|
return {
|
|
100
130
|
content: [{ type: 'text', text: JSON.stringify(result.data, null, 2) }],
|
|
101
131
|
};
|
|
@@ -112,4 +142,4 @@ export async function handleUpload(args: { file_path: string; folder?: string })
|
|
|
112
142
|
isError: true,
|
|
113
143
|
};
|
|
114
144
|
}
|
|
115
|
-
}
|
|
145
|
+
}
|
package/src/utils/http-client.ts
CHANGED
|
@@ -5,91 +5,128 @@ import http from 'http';
|
|
|
5
5
|
import https from 'https';
|
|
6
6
|
import { McpConfigResponse, McpUploadResponse } from '../types/index.js';
|
|
7
7
|
|
|
8
|
+
const MAX_RETRIES = 2;
|
|
9
|
+
|
|
8
10
|
export class HttpClient {
|
|
9
|
-
private baseUrl: string
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
private get baseUrl(): string {
|
|
12
|
+
return process.env.SMARTORDER_API_BASE || 'https://smart-order.raiseinfo.cn';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
private get tenantCode(): string {
|
|
16
|
+
return process.env.TENANT_CODE || '';
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
private get mcpToken(): string {
|
|
20
|
+
return process.env.MCP_TOKEN || '';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
private get authHeaders(): Record<string, string> {
|
|
24
|
+
return {
|
|
25
|
+
'X-Tenant-Code': this.tenantCode,
|
|
26
|
+
'X-Mcp-Token': this.mcpToken,
|
|
27
|
+
};
|
|
17
28
|
}
|
|
18
29
|
|
|
19
30
|
async getConfig(): Promise<McpConfigResponse> {
|
|
20
31
|
const url = `${this.baseUrl}/api/mcp/config`;
|
|
32
|
+
console.log('[HTTP] GET', url);
|
|
21
33
|
return this.request('GET', url) as Promise<McpConfigResponse>;
|
|
22
34
|
}
|
|
23
35
|
|
|
24
|
-
async uploadFile(filePath: string, folder: string): Promise<McpUploadResponse> {
|
|
25
|
-
const url = `${this.baseUrl}/api/mcp/upload`;
|
|
26
|
-
|
|
36
|
+
async uploadFile(filePath: string, folder: string, apiUrl?: string): Promise<McpUploadResponse> {
|
|
37
|
+
const url = apiUrl || `${this.baseUrl}/api/mcp/upload`;
|
|
38
|
+
return this.uploadWithRetry(filePath, folder, url);
|
|
39
|
+
}
|
|
27
40
|
|
|
28
|
-
|
|
29
|
-
|
|
41
|
+
private async uploadWithRetry(
|
|
42
|
+
filePath: string,
|
|
43
|
+
folder: string,
|
|
44
|
+
url: string,
|
|
45
|
+
attempt: number = 1
|
|
46
|
+
): Promise<McpUploadResponse> {
|
|
47
|
+
console.log(`[HTTP] Upload attempt ${attempt}/${MAX_RETRIES + 1}:`, filePath);
|
|
30
48
|
|
|
31
|
-
|
|
32
|
-
|
|
49
|
+
try {
|
|
50
|
+
return await this.doUpload(filePath, folder, url);
|
|
51
|
+
} catch (error: any) {
|
|
52
|
+
console.error(`[HTTP] Upload attempt ${attempt} failed:`, error.message);
|
|
33
53
|
|
|
34
|
-
|
|
54
|
+
if (attempt <= MAX_RETRIES) {
|
|
55
|
+
console.log(`[HTTP] Retrying... (${attempt + 1}/${MAX_RETRIES + 1})`);
|
|
56
|
+
return this.uploadWithRetry(filePath, folder, url, attempt + 1);
|
|
57
|
+
}
|
|
58
|
+
throw error;
|
|
59
|
+
}
|
|
35
60
|
}
|
|
36
61
|
|
|
37
|
-
private
|
|
38
|
-
method: string,
|
|
39
|
-
url: string,
|
|
40
|
-
body?: any,
|
|
41
|
-
isFormData: boolean = false
|
|
42
|
-
): Promise<any> {
|
|
62
|
+
private doUpload(filePath: string, folder: string, url: string): Promise<McpUploadResponse> {
|
|
43
63
|
return new Promise((resolve, reject) => {
|
|
64
|
+
const form = new FormData();
|
|
65
|
+
form.append('file', fs.createReadStream(filePath), { filename: path.basename(filePath) });
|
|
66
|
+
form.append('folder', folder);
|
|
67
|
+
|
|
44
68
|
const urlObj = new URL(url);
|
|
45
69
|
const client = urlObj.protocol === 'https:' ? https : http;
|
|
46
70
|
|
|
47
|
-
const
|
|
71
|
+
const req = client.request({
|
|
48
72
|
hostname: urlObj.hostname,
|
|
49
73
|
port: urlObj.port || (urlObj.protocol === 'https:' ? 443 : 80),
|
|
50
74
|
path: urlObj.pathname,
|
|
51
|
-
method,
|
|
52
|
-
headers: {
|
|
53
|
-
'X-Tenant-Code': this.tenantCode,
|
|
54
|
-
'X-Mcp-Token': this.mcpToken,
|
|
55
|
-
...(isFormData ? body.getHeaders() : { 'Content-Type': 'application/json' }),
|
|
56
|
-
},
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
const req = client.request(options, (res) => {
|
|
60
|
-
let data = '';
|
|
61
|
-
res.on('data', (chunk) => (data += chunk));
|
|
62
|
-
res.on('end', () => {
|
|
63
|
-
try {
|
|
64
|
-
const json = JSON.parse(data);
|
|
65
|
-
if (res.statusCode === 200) {
|
|
66
|
-
resolve(json);
|
|
67
|
-
} else if (res.statusCode === 401 || res.statusCode === 403) {
|
|
68
|
-
reject(new Error('认证失败,请检查租户Token配置'));
|
|
69
|
-
} else if (res.statusCode === 404) {
|
|
70
|
-
reject(new Error('上传服务路径不存在,请联系管理员'));
|
|
71
|
-
} else {
|
|
72
|
-
reject(new Error(`服务返回错误:${res.statusCode}`));
|
|
73
|
-
}
|
|
74
|
-
} catch {
|
|
75
|
-
reject(new Error('响应解析失败'));
|
|
76
|
-
}
|
|
77
|
-
});
|
|
75
|
+
method: 'POST',
|
|
76
|
+
headers: { ...this.authHeaders, ...form.getHeaders() },
|
|
78
77
|
});
|
|
79
78
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
79
|
+
this.handleResponse(req, resolve, reject);
|
|
80
|
+
req.on('error', (err) => reject(new Error(`网络错误:${err.message}`)));
|
|
81
|
+
form.pipe(req);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
83
84
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
req.write(JSON.stringify(body));
|
|
89
|
-
}
|
|
90
|
-
}
|
|
85
|
+
private request(method: string, url: string): Promise<any> {
|
|
86
|
+
return new Promise((resolve, reject) => {
|
|
87
|
+
const urlObj = new URL(url);
|
|
88
|
+
const client = urlObj.protocol === 'https:' ? https : http;
|
|
91
89
|
|
|
90
|
+
const req = client.request({
|
|
91
|
+
hostname: urlObj.hostname,
|
|
92
|
+
port: urlObj.port || (urlObj.protocol === 'https:' ? 443 : 80),
|
|
93
|
+
path: urlObj.pathname,
|
|
94
|
+
method,
|
|
95
|
+
headers: { ...this.authHeaders, 'Content-Type': 'application/json' },
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
this.handleResponse(req, resolve, reject);
|
|
99
|
+
req.on('error', (err) => reject(new Error(`网络错误:${err.message}`)));
|
|
92
100
|
req.end();
|
|
93
101
|
});
|
|
94
102
|
}
|
|
103
|
+
|
|
104
|
+
private handleResponse(
|
|
105
|
+
req: http.ClientRequest,
|
|
106
|
+
resolve: (value: any) => void,
|
|
107
|
+
reject: (reason: any) => void
|
|
108
|
+
): void {
|
|
109
|
+
req.on('response', (res) => {
|
|
110
|
+
let data = '';
|
|
111
|
+
res.on('data', (chunk) => (data += chunk));
|
|
112
|
+
res.on('end', () => {
|
|
113
|
+
console.log('[HTTP] Response:', res.statusCode, data.substring(0, 200));
|
|
114
|
+
|
|
115
|
+
try {
|
|
116
|
+
const json = JSON.parse(data);
|
|
117
|
+
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
|
|
118
|
+
resolve(json);
|
|
119
|
+
} else if (res.statusCode === 401 || res.statusCode === 403) {
|
|
120
|
+
reject(new Error('认证失败,请检查租户Token配置'));
|
|
121
|
+
} else if (res.statusCode === 404) {
|
|
122
|
+
reject(new Error('上传服务路径不存在,请联系管理员'));
|
|
123
|
+
} else {
|
|
124
|
+
reject(new Error(`服务返回错误:${res.statusCode}`));
|
|
125
|
+
}
|
|
126
|
+
} catch (e) {
|
|
127
|
+
reject(new Error('响应解析失败: ' + data.substring(0, 100)));
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
}
|
|
95
132
|
}
|