MCPcopy Create free account
hub / github.com/EvoMap/evolver / _handleRequest

Method _handleRequest

src/proxy/server/http.js:187–254  ·  view source on GitHub ↗
(req, res)

Source from the content-addressed store, hash-verified

185 }
186
187 async _handleRequest(req, res) {
188 const authHeader = req.headers['authorization'] || '';
189 const provided = authHeader.startsWith('Bearer ') ? authHeader.slice(7) : '';
190 const provBuf = Buffer.from(provided, 'utf8');
191 // Primary token plus any grace tokens from settings.json::proxy.previous_tokens.
192 // The grace list is the recovery path for the rare case where settings.json was
193 // wiped externally (logout, manual rm) while long-lived CC sessions still hold
194 // the pre-wipe token in their fork-time env. Operator writes the lost token into
195 // previous_tokens; once those sessions close, the operator can clear the array.
196 // Reading directly from settings.json (instead of an env shim) keeps the
197 // single source of truth on disk — no python bridge in the daemon hook.
198 // Defense in depth: even though start() filters non-strings before persisting,
199 // settings.json can be hand-edited between requests, so re-validate every read.
200 // A non-string slipping into Buffer.from below would throw ERR_INVALID_ARG_TYPE
201 // and unhandled-reject through the auth path.
202 const previous = readSettings().proxy?.previous_tokens;
203 const extras = Array.isArray(previous)
204 ? previous
205 .map((t) => (typeof t === 'string' ? t.trim() : ''))
206 .filter((t) => isValidReusableProxyToken(t))
207 : [];
208 const candidates = [this.token, ...extras]
209 .filter((t) => isValidReusableProxyToken(t))
210 .map((t) => t.trim());
211 let valid = false;
212 for (const cand of candidates) {
213 const expBuf = Buffer.from(cand, 'utf8');
214 if (provBuf.length === expBuf.length && crypto.timingSafeEqual(provBuf, expBuf)) {
215 valid = true;
216 break;
217 }
218 }
219 if (!valid) {
220 return sendJson(res, 401, { error: 'Unauthorized' });
221 }
222
223 const url = new URL(req.url, `http://127.0.0.1:${this.actualPort}`);
224 const routeKey = `${req.method} ${url.pathname}`;
225
226 const paramMatch = this._matchRoute(req.method, url.pathname);
227
228 if (!paramMatch) {
229 return sendJson(res, 404, { error: 'Not found', path: url.pathname });
230 }
231
232 const { handler, params } = paramMatch;
233
234 try {
235 const body = (req.method === 'POST' || req.method === 'PUT') ? await parseBody(req) : {};
236 const query = Object.fromEntries(url.searchParams);
237 const headers = req.headers;
238 const result = await handler({ body, query, params, headers });
239 if (result && result.stream) {
240 await this._streamResponse(res, result);
241 } else {
242 sendJson(res, result.status || 200, result.body || result, result.headers);
243 }
244 } catch (err) {

Callers 8

withServerFunction · 0.95
withServerFunction · 0.95
withServerFunction · 0.95
withServerFunction · 0.95
withServerFunction · 0.95
withServerFunction · 0.95
startMethod · 0.95

Calls 6

_matchRouteMethod · 0.95
_streamResponseMethod · 0.95
readSettingsFunction · 0.85
parseBodyFunction · 0.85
sendJsonFunction · 0.70

Tested by 6

withServerFunction · 0.76
withServerFunction · 0.76
withServerFunction · 0.76
withServerFunction · 0.76
withServerFunction · 0.76
withServerFunction · 0.76