Skip to content

Commit 0303711

Browse files
committed
fix: Add pre-flight BookStack connectivity check before every chat request
- Add checkBookStackConnectivity() that pings /api/books with a 7s timeout - Detects 403 (VPN blocked), 401, 5xx, and all network error codes as unreachable - Immediately sends bookstack_error SSE event and aborts before calling OpenAI - Prevents misleading 'no documentation found' GPT responses when VPN is off - Adds axios 7s global timeout so hung requests fail fast instead of waiting indefinitely
1 parent 2e900f9 commit 0303711

1 file changed

Lines changed: 38 additions & 1 deletion

File tree

chatbot/server.js

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,38 @@ const bookstackApi = axios.create({
3030
headers: {
3131
'Authorization': `Token ${BOOKSTACK_TOKEN_ID}:${BOOKSTACK_TOKEN_SECRET}`,
3232
'Content-Type': 'application/json'
33-
}
33+
},
34+
timeout: 7000 // 7 s — fast-fail when VPN is off
3435
});
3536

37+
// Pre-flight connectivity check — run before every chat request
38+
// Returns true if BookStack is reachable, false otherwise.
39+
async function checkBookStackConnectivity() {
40+
try {
41+
await bookstackApi.get('/books', { params: { count: 1 } });
42+
return true;
43+
} catch (err) {
44+
const status = err.response?.status;
45+
// 403 = server is up but VPN / access is blocked
46+
// 401 = bad token (treat as unreachable — user can't get docs either)
47+
// 5xx, network codes = server down / VPN not connected
48+
if (
49+
err.code === 'ECONNREFUSED' ||
50+
err.code === 'ENOTFOUND' ||
51+
err.code === 'ETIMEDOUT' ||
52+
err.code === 'ECONNRESET' ||
53+
err.code === 'ECONNABORTED' ||
54+
status === 401 || status === 403 ||
55+
(status && status >= 500)
56+
) {
57+
console.warn(`BookStack connectivity check failed — code: ${err.code || status}`);
58+
return false;
59+
}
60+
// Unknown error — assume reachable so we don't block on transient issues
61+
return true;
62+
}
63+
}
64+
3665
async function searchBookStack(query, count = 10) {
3766
try {
3867
const res = await bookstackApi.get('/search', { params: { query, count } });
@@ -175,6 +204,14 @@ app.post('/api/chat', async (req, res) => {
175204
res.setHeader('X-Accel-Buffering', 'no');
176205

177206
try {
207+
// ── Pre-flight: verify BookStack is reachable before doing anything ──
208+
const bookStackOnline = await checkBookStackConnectivity();
209+
if (!bookStackOnline) {
210+
res.write(`data: ${JSON.stringify({ type: 'bookstack_error', content: 'Cannot reach BookStack' })}\n\n`);
211+
res.end();
212+
return;
213+
}
214+
178215
res.write(`data: ${JSON.stringify({ type: 'status', content: 'Searching documentation...' })}\n\n`);
179216

180217
// Multi-query strategy

0 commit comments

Comments
 (0)