Spaces:
Running
Running
Update app.js
Browse files
app.js
CHANGED
@@ -1,5 +1,4 @@
|
|
1 |
-
const
|
2 |
-
const url = require('url');
|
3 |
const fetch = require('node-fetch');
|
4 |
|
5 |
const MODEL = 'claude-3-5-sonnet@20240620';
|
@@ -46,6 +45,7 @@ async function getAccessToken() {
|
|
46 |
});
|
47 |
|
48 |
const data = await response.json();
|
|
|
49 |
tokenCache.accessToken = data.access_token;
|
50 |
tokenCache.expiry = now + data.expires_in;
|
51 |
} finally {
|
@@ -63,150 +63,87 @@ function getLocation() {
|
|
63 |
}
|
64 |
|
65 |
function constructApiUrl(location) {
|
66 |
-
|
67 |
-
console.log('Constructed URL:', url); // 打印URL以验证其正确性
|
68 |
-
return url;
|
69 |
}
|
70 |
|
71 |
-
async function handleRequest(
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
}
|
76 |
-
|
77 |
-
const apiKey = request.headers['x-api-key'];
|
78 |
-
if (apiKey !== API_KEY) {
|
79 |
-
return handleErrorResponse(403, {
|
80 |
-
type: "error",
|
81 |
-
error: {
|
82 |
-
type: "permission_error",
|
83 |
-
message: "Your API key does not have permission to use the specified resource."
|
84 |
-
}
|
85 |
-
});
|
86 |
-
}
|
87 |
-
|
88 |
-
const accessToken = await getAccessToken();
|
89 |
-
const location = getLocation();
|
90 |
-
const apiUrl = constructApiUrl(location);
|
91 |
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
delete requestBody.anthropic_version;
|
96 |
-
}
|
97 |
-
|
98 |
-
if (requestBody.model) {
|
99 |
-
delete requestBody.model;
|
100 |
-
}
|
101 |
-
|
102 |
-
requestBody.anthropic_version = "vertex-2023-10-16";
|
103 |
-
|
104 |
-
const modifiedHeaders = {
|
105 |
-
...request.headers,
|
106 |
-
'Authorization': `Bearer ${accessToken}`,
|
107 |
-
'Content-Type': 'application/json; charset=utf-8'
|
108 |
-
};
|
109 |
-
delete modifiedHeaders['anthropic-version'];
|
110 |
-
|
111 |
-
const modifiedRequest = {
|
112 |
-
headers: modifiedHeaders,
|
113 |
-
method: request.method,
|
114 |
-
body: JSON.stringify(requestBody),
|
115 |
-
redirect: 'manual'
|
116 |
-
};
|
117 |
-
|
118 |
-
const response = await fetch(apiUrl, modifiedRequest);
|
119 |
-
if (response.status === 301 || response.status === 302) {
|
120 |
-
const location = response.headers.get('location');
|
121 |
-
console.log('Redirected to:', location);
|
122 |
-
const redirectedResponse = await fetch(location, modifiedRequest);
|
123 |
-
return handleResponse(redirectedResponse);
|
124 |
-
}
|
125 |
-
return handleResponse(response);
|
126 |
-
} catch (error) {
|
127 |
-
console.error('Error handling request:', error);
|
128 |
-
return handleErrorResponse(500, {
|
129 |
type: "error",
|
130 |
error: {
|
131 |
-
type: "
|
132 |
-
message: "
|
133 |
}
|
134 |
});
|
|
|
135 |
}
|
136 |
-
}
|
137 |
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
headers: {
|
142 |
-
...response.headers,
|
143 |
-
'Access-Control-Allow-Origin': '*',
|
144 |
-
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
|
145 |
-
'Access-Control-Allow-Headers': 'Content-Type, Authorization, x-api-key, anthropic-version, model'
|
146 |
-
},
|
147 |
-
body: response.body
|
148 |
-
};
|
149 |
-
}
|
150 |
-
|
151 |
-
function handleErrorResponse(status, body) {
|
152 |
-
return {
|
153 |
-
status: status,
|
154 |
-
headers: {
|
155 |
-
'Content-Type': 'application/json',
|
156 |
-
'Access-Control-Allow-Origin': '*',
|
157 |
-
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS, DELETE, HEAD',
|
158 |
-
'Access-Control-Allow-Headers': 'Content-Type, Authorization, x-api-key, anthropic-version, model'
|
159 |
-
},
|
160 |
-
body: JSON.stringify(body)
|
161 |
-
};
|
162 |
-
}
|
163 |
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
'Access-Control-Allow-Headers': 'Content-Type, Authorization, x-api-key, anthropic-version, model'
|
169 |
-
};
|
170 |
-
|
171 |
-
return {
|
172 |
-
status: 204,
|
173 |
-
headers: headers
|
174 |
-
};
|
175 |
-
}
|
176 |
-
|
177 |
-
const server = http.createServer(async (req, res) => {
|
178 |
-
const parsedUrl = url.parse(req.url, true);
|
179 |
-
if (parsedUrl.pathname === '/ai/v1/messages') {
|
180 |
-
const request = {
|
181 |
-
method: req.method,
|
182 |
-
headers: req.headers,
|
183 |
-
body: await getRequestBody(req)
|
184 |
-
};
|
185 |
-
|
186 |
-
const response = await handleRequest(request);
|
187 |
-
res.writeHead(response.status, response.headers);
|
188 |
-
res.end(response.body);
|
189 |
-
} else {
|
190 |
-
res.writeHead(404, { 'Content-Type': 'application/json' });
|
191 |
-
res.end(JSON.stringify({ error: 'Not Found' }));
|
192 |
}
|
193 |
-
|
|
|
|
|
|
|
|
|
|
|
194 |
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
|
|
|
|
|
|
200 |
});
|
201 |
-
|
202 |
-
|
|
|
|
|
203 |
});
|
204 |
-
|
205 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
206 |
});
|
207 |
-
}
|
208 |
}
|
209 |
|
210 |
-
|
211 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
212 |
});
|
|
|
1 |
+
const express = require('express');
|
|
|
2 |
const fetch = require('node-fetch');
|
3 |
|
4 |
const MODEL = 'claude-3-5-sonnet@20240620';
|
|
|
45 |
});
|
46 |
|
47 |
const data = await response.json();
|
48 |
+
|
49 |
tokenCache.accessToken = data.access_token;
|
50 |
tokenCache.expiry = now + data.expires_in;
|
51 |
} finally {
|
|
|
63 |
}
|
64 |
|
65 |
function constructApiUrl(location) {
|
66 |
+
return `https://${location}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/${location}/publishers/anthropic/models/${MODEL}:streamRawPredict`;
|
|
|
|
|
67 |
}
|
68 |
|
69 |
+
async function handleRequest(req, res) {
|
70 |
+
if (req.method === 'OPTIONS') {
|
71 |
+
return handleOptions(res);
|
72 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
|
74 |
+
const apiKey = req.headers['x-api-key'];
|
75 |
+
if (apiKey !== API_KEY) {
|
76 |
+
res.status(403).json({
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
type: "error",
|
78 |
error: {
|
79 |
+
type: "permission_error",
|
80 |
+
message: "Your API key does not have permission to use the specified resource."
|
81 |
}
|
82 |
});
|
83 |
+
return;
|
84 |
}
|
|
|
85 |
|
86 |
+
const accessToken = await getAccessToken();
|
87 |
+
const location = getLocation();
|
88 |
+
const apiUrl = constructApiUrl(location);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
89 |
|
90 |
+
let requestBody = req.body;
|
91 |
+
|
92 |
+
if (requestBody.anthropic_version) {
|
93 |
+
delete requestBody.anthropic_version;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
}
|
95 |
+
|
96 |
+
if (requestBody.model) {
|
97 |
+
delete requestBody.model;
|
98 |
+
}
|
99 |
+
|
100 |
+
requestBody.anthropic_version = "vertex-2023-10-16";
|
101 |
|
102 |
+
try {
|
103 |
+
const response = await fetch(apiUrl, {
|
104 |
+
method: 'POST',
|
105 |
+
headers: {
|
106 |
+
'Authorization': `Bearer ${accessToken}`,
|
107 |
+
'Content-Type': 'application/json; charset=utf-8'
|
108 |
+
},
|
109 |
+
body: JSON.stringify(requestBody)
|
110 |
});
|
111 |
+
|
112 |
+
res.status(response.status);
|
113 |
+
response.headers.forEach((value, name) => {
|
114 |
+
res.setHeader(name, value);
|
115 |
});
|
116 |
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
117 |
+
res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS');
|
118 |
+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, x-api-key, anthropic-version, model');
|
119 |
+
|
120 |
+
response.body.pipe(res);
|
121 |
+
} catch (error) {
|
122 |
+
console.error('Error:', error);
|
123 |
+
res.status(500).json({
|
124 |
+
type: "error",
|
125 |
+
error: {
|
126 |
+
type: "internal_server_error",
|
127 |
+
message: "An unexpected error occurred while processing your request."
|
128 |
+
}
|
129 |
});
|
130 |
+
}
|
131 |
}
|
132 |
|
133 |
+
function handleOptions(res) {
|
134 |
+
res.status(204);
|
135 |
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
136 |
+
res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS');
|
137 |
+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, x-api-key, anthropic-version, model');
|
138 |
+
res.end();
|
139 |
+
}
|
140 |
+
|
141 |
+
const app = express();
|
142 |
+
app.use(express.json());
|
143 |
+
|
144 |
+
app.all('/ai/v1/messages', handleRequest);
|
145 |
+
|
146 |
+
const PORT = 8080;
|
147 |
+
app.listen(PORT, () => {
|
148 |
+
console.log(`Server is running on port ${PORT}`);
|
149 |
});
|