MCPcopy Create free account
hub / github.com/78/tenbox / ForwardToUpstream

Method ForwardToUpstream

src/manager/llm_proxy.cpp:463–754  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

461}
462
463bool LlmProxyService::ForwardToUpstream(uintptr_t client_sock,
464 const settings::LlmModelMapping& mapping,
465 const std::string& modified_body,
466 bool is_streaming, bool keep_alive,
467 int& out_status, std::string& out_response_body,
468 StreamEndInfo& out_stream_end) {
469 SOCKET client = static_cast<SOCKET>(client_sock);
470 const uint64_t t_start = NowMonotonicMs();
471
472 // Default classification: becomes "n/a" for non-streaming, otherwise
473 // overwritten by the SSE loop below.
474 out_stream_end.reason = is_streaming ? "unknown" : "n/a";
475
476 auto set_handshake_error = [&](const std::string& msg, uint32_t err = 0) {
477 out_stream_end.reason = "handshake_error";
478 out_stream_end.detail = msg;
479 out_stream_end.winhttp_error = err;
480 out_stream_end.duration_ms = NowMonotonicMs() - t_start;
481 };
482
483 // Build upstream URL: target_url + /chat/completions
484 std::string upstream_url = mapping.target_url;
485 // Ensure no trailing slash duplication
486 if (!upstream_url.empty() && upstream_url.back() == '/')
487 upstream_url.pop_back();
488 upstream_url += "/chat/completions";
489
490 UrlParts parts;
491 if (!ParseUrl(upstream_url, parts)) {
492 set_handshake_error("invalid_upstream_url");
493 SendErrorResponse(client_sock, 502, "Bad Gateway",
494 "Invalid upstream URL: " + mapping.target_url, keep_alive);
495 return false;
496 }
497
498 HINTERNET session = WinHttpOpen(L"TenBox-LLM-Proxy/1.0",
499 WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
500 WINHTTP_NO_PROXY_NAME,
501 WINHTTP_NO_PROXY_BYPASS, 0);
502 if (!session) {
503 set_handshake_error("WinHttpOpen failed", GetLastError());
504 SendErrorResponse(client_sock, 502, "Bad Gateway",
505 "WinHttpOpen failed", keep_alive);
506 return false;
507 }
508
509 // Set explicit WinHTTP timeouts. Default receive timeout (30s) is too short for SSE streams.
510 if (!WinHttpSetTimeouts(session, 15000, 60000, 30000, 300000)) {
511 DWORD err = GetLastError();
512 LOG_ERROR("WinHttpSetTimeouts failed: %lu", err);
513 }
514
515 // Enable HTTP/1.1 keep-alive (default in WinHTTP)
516 HINTERNET conn = WinHttpConnect(session, parts.host.c_str(), parts.port, 0);
517 if (!conn) {
518 DWORD err = GetLastError();
519 set_handshake_error("WinHttpConnect failed", err);
520 WinHttpCloseHandle(session);

Callers

nothing calls this directly

Calls 10

WsaErrorNameFunction · 0.85
WinHttpErrorNameFunction · 0.85
NowMonotonicMsFunction · 0.70
ParseUrlFunction · 0.70
Utf8ToWideFunction · 0.70
SendStrFunction · 0.70
ToHexFunction · 0.70
SendAllFunction · 0.70
sizeMethod · 0.45
dataMethod · 0.45

Tested by

no test coverage detected