Skip to content

Commit a6f5941

Browse files
committed
fix: correctly propagate errors from the ai proxy
1 parent e55a8b4 commit a6f5941

File tree

3 files changed

+62
-15
lines changed

3 files changed

+62
-15
lines changed

assets/components/modai/js/mgr/executor.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,10 @@
224224

225225
if (!res.ok) {
226226
const data = await res.json();
227+
if (data.error) {
228+
throw new Error(data.error.message);
229+
}
230+
227231
throw new Error(data.detail);
228232
}
229233

@@ -241,6 +245,10 @@
241245

242246
if (!res.ok) {
243247
const data = await res.json();
248+
if (data.error) {
249+
throw new Error(data.error.message);
250+
}
251+
244252
throw new Error(data.detail);
245253
}
246254

@@ -251,7 +259,7 @@
251259

252260
if (!proxy) {
253261
const data = await res.json();
254-
return serviceExecutor(data.object, onChunkStream);
262+
return serviceExecutor(data, onChunkStream);
255263
}
256264

257265
if (!stream) {

core/components/modai/src/API/API.php

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ protected function success($data): void {
126126

127127
protected function proxyAIResponse(AIResponse $aiResponse)
128128
{
129-
$headerStream = (int)$aiResponse->getStream();
129+
$headerStream = (int)$aiResponse->isStream();
130130
header("x-modai-service: {$aiResponse->getService()}");
131131
header("x-modai-parser: {$aiResponse->getParser()}");
132132
header("x-modai-stream: $headerStream");
@@ -137,7 +137,7 @@ protected function proxyAIResponse(AIResponse $aiResponse)
137137
$this->success([
138138
'forExecutor' => [
139139
'service' => $aiResponse->getService(),
140-
'stream' => $aiResponse->getStream(),
140+
'stream' => $aiResponse->isStream(),
141141
'parser' => $aiResponse->getParser(),
142142
'url' => $aiResponse->getUrl(),
143143
'headers' => $aiResponse->getHeaders(),
@@ -155,24 +155,53 @@ protected function proxyAIResponse(AIResponse $aiResponse)
155155
}
156156

157157
$ch = curl_init($aiResponse->getUrl());
158-
curl_setopt($ch, CURLOPT_RETURNTRANSFER, !$aiResponse->getStream());
158+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, !$aiResponse->isStream());
159159
curl_setopt($ch, CURLOPT_POST, true);
160160
curl_setopt($ch, CURLOPT_POSTFIELDS, $aiResponse->getBody());
161161
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
162+
curl_setopt($ch, CURLOPT_HEADER, false);
163+
164+
$statusCode = 200;
165+
$headersSent = false;
166+
$bodyBuffer = '';
167+
168+
169+
if ($aiResponse->isStream()) {
170+
curl_setopt($ch, CURLOPT_HEADERFUNCTION, function ($curl, $header_line) use (&$statusCode) {
171+
if (strpos($header_line, 'HTTP/') === 0) {
172+
preg_match('#HTTP/\S+ (\d+)#', $header_line, $matches);
173+
if (isset($matches[1])) {
174+
$statusCode = (int)$matches[1];
175+
}
176+
}
177+
return strlen($header_line);
178+
});
162179

163-
if ($aiResponse->getStream()) {
164180
header('Content-Type: text/event-stream');
165181
header('Connection: keep-alive');
166182
header('Cache-Control: no-cache');
167183
flush();
168184
ob_flush();
169185

170-
curl_setopt($ch, CURLOPT_WRITEFUNCTION, function ($curl, $chunk) {
171-
echo $chunk;
172-
flush();
173-
ob_flush();
174-
175-
return strlen($chunk);
186+
curl_setopt($ch, CURLOPT_WRITEFUNCTION, function ($curl, $chunk) use (&$statusCode, &$headersSent, &$bodyBuffer) {
187+
if ($statusCode >= 400) {
188+
$bodyBuffer .= $chunk;
189+
return strlen($chunk);
190+
} else {
191+
if (!$headersSent) {
192+
header('Content-Type: text/event-stream');
193+
header('Connection: keep-alive');
194+
header('Cache-Control: no-cache');
195+
flush();
196+
ob_flush();
197+
$headersSent = true;
198+
}
199+
200+
echo $chunk;
201+
flush();
202+
ob_flush();
203+
return strlen($chunk);
204+
}
176205
});
177206
}
178207

@@ -183,10 +212,20 @@ protected function proxyAIResponse(AIResponse $aiResponse)
183212
throw new \Exception($error_msg);
184213
}
185214

186-
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
187-
http_response_code($httpCode);
215+
if (!$aiResponse->isStream()) {
216+
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
217+
$bodyBuffer = $response;
218+
}
219+
220+
http_response_code($statusCode);
221+
222+
if ($statusCode >= 400) {
223+
header('Content-Type: application/json');
224+
echo $bodyBuffer;
225+
return;
226+
}
188227

189-
if (!$aiResponse->getStream()) {
228+
if (!$aiResponse->isStream()) {
190229
header("Content-Type: application/json");
191230
echo $response;
192231
return;

core/components/modai/src/Services/Response/AIResponse.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public function getBody(): string
7272
return json_encode($this->body);
7373
}
7474

75-
public function getStream(): bool
75+
public function isStream(): bool
7676
{
7777
return $this->stream;
7878
}

0 commit comments

Comments
 (0)