MCPcopy
hub / github.com/coder/mux / ManagedAPIProvider

Function ManagedAPIProvider

src/browser/contexts/API.tsx:184–656  ·  view source on GitHub ↗
(props: Omit<APIProviderProps, "client">)

Source from the content-addressed store, hash-verified

182}
183
184function ManagedAPIProvider(props: Omit<APIProviderProps, "client">) {
185 const [state, setState] = useState<ConnectionState>({ status: "connecting" });
186 const [authToken, setAuthToken] = useState<string | null>(() => {
187 const urlParams = new URLSearchParams(window.location.search);
188 const urlToken = urlParams.get("token")?.trim();
189 if (urlToken) {
190 setStoredAuthToken(urlToken);
191 // Strip token from URL so it doesn't leak into bookmarks, browser
192 // history, PWA launch URLs, or Referer headers.
193 const cleanUrl = new URL(window.location.href);
194 cleanUrl.searchParams.delete("token");
195 window.history.replaceState({}, "", cleanUrl.pathname + cleanUrl.search);
196 return urlToken;
197 }
198
199 return getStoredAuthToken();
200 });
201
202 const cleanupRef = useRef<(() => void) | null>(null);
203 const hasConnectedRef = useRef(false);
204 const reconnectAttemptRef = useRef(0);
205 const reconnectTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
206 const scheduleReconnectRef = useRef<(() => void) | null>(null);
207 const consecutivePingFailuresRef = useRef(0);
208 const connectionIdRef = useRef(0);
209 const forceReconnectInProgressRef = useRef(false);
210 const livenessPingsInFlightCountRef = useRef(0);
211 const lastInboundBrowserFrameAtRef = useRef(0);
212
213 // When we decide the user needs to provide a token, stop the reconnect loop.
214 //
215 // Otherwise, the WebSocket close event (triggered by cleanup()) can schedule a reconnect
216 // which immediately flips the UI back to "reconnecting", causing the AuthTokenModal
217 // to flicker.
218 const authRequiredRef = useRef(false);
219
220 const authProbeAttemptedRef = useRef(false);
221 const wsFactory = useMemo(
222 () => props.createWebSocket ?? ((url: string) => new WebSocket(url)),
223 [props.createWebSocket]
224 );
225
226 const connect = useCallback(
227 (token: string | null) => {
228 const connectionId = ++connectionIdRef.current;
229 // Reset per-connection inbound traffic tracking so stale timestamps from a prior
230 // socket cannot suppress liveness pings on the next connection.
231 lastInboundBrowserFrameAtRef.current = 0;
232 livenessPingsInFlightCountRef.current = 0;
233
234 authRequiredRef.current = false;
235
236 // This connect() call supersedes any prior pending reconnect or active connection.
237 if (reconnectTimeoutRef.current) {
238 clearTimeout(reconnectTimeoutRef.current);
239 reconnectTimeoutRef.current = null;
240 }
241

Callers

nothing calls this directly

Calls 15

setStoredAuthTokenFunction · 0.90
getStoredAuthTokenFunction · 0.90
getErrorMessageFunction · 0.90
clearStoredAuthTokenFunction · 0.90
getBrowserBackendBaseUrlFunction · 0.90
createElectronClientFunction · 0.85
createBrowserClientFunction · 0.85
connectFunction · 0.85
checkLivenessFunction · 0.85
getMethod · 0.65
abortMethod · 0.65

Tested by

no test coverage detected