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

Function startLoopbackServer

src/node/utils/oauthLoopbackServer.ts:128–294  ·  view source on GitHub ↗
(options: LoopbackServerOptions)

Source from the content-addressed store, hash-verified

126 * after token exchange).
127 */
128export async function startLoopbackServer(options: LoopbackServerOptions): Promise<LoopbackServer> {
129 const port = options.port ?? 0;
130 const host = options.host ?? "127.0.0.1";
131 // `server.listen()` expects IPv6 hosts without brackets, but callers may pass
132 // "[::1]" since that's what URLs require.
133 const listenHost = host.startsWith("[") && host.endsWith("]") ? host.slice(1, -1) : host;
134 const callbackPath = options.callbackPath ?? "/callback";
135 const validateLoopback = options.validateLoopback ?? false;
136 const deferSuccessResponse = options.deferSuccessResponse ?? false;
137
138 const deferred = createDeferred<Result<LoopbackCallbackResult, string>>();
139 let deferredSuccessResponse: http.ServerResponse | null = null;
140
141 const render =
142 options.renderHtml ??
143 ((r: { success: boolean; error?: string }) =>
144 renderOAuthCallbackHtml({
145 title: r.success ? "Login complete" : "Login failed",
146 message: r.success
147 ? "You can return to Mux. You may now close this tab."
148 : (r.error ?? "Unknown error"),
149 success: r.success,
150 }));
151
152 const clearDeferredSuccessResponse = (response: http.ServerResponse) => {
153 if (deferredSuccessResponse === response) {
154 deferredSuccessResponse = null;
155 }
156 };
157
158 const sendDeferredResponse = (result: { success: boolean; error?: string }) => {
159 const pendingResponse = deferredSuccessResponse;
160 if (!pendingResponse || pendingResponse.writableEnded || pendingResponse.destroyed) {
161 deferredSuccessResponse = null;
162 return;
163 }
164
165 deferredSuccessResponse = null;
166 pendingResponse.statusCode = result.success ? 200 : 400;
167 pendingResponse.setHeader("Content-Type", "text/html");
168 pendingResponse.end(render(result));
169 };
170
171 const sendSuccessResponse = () => {
172 sendDeferredResponse({ success: true });
173 };
174
175 const sendFailureResponse = (error: string) => {
176 sendDeferredResponse({ success: false, error });
177 };
178
179 const sendCancelledResponseIfPending = () => {
180 sendFailureResponse("OAuth flow cancelled");
181 };
182
183 const server = http.createServer((req, res) => {
184 // Optionally reject non-loopback connections (Codex sets validateLoopback: true).
185 if (validateLoopback && !isLoopbackAddress(req.socket.remoteAddress)) {

Callers 4

startDesktopFlowMethod · 0.90
startDesktopFlowMethod · 0.90
startDesktopFlowMethod · 0.90

Calls 14

createDeferredFunction · 0.90
renderOAuthCallbackHtmlFunction · 0.90
ErrFunction · 0.90
OkFunction · 0.90
closeServerFunction · 0.90
isLoopbackAddressFunction · 0.85
hostForRedirectUriFunction · 0.85
resolveMethod · 0.80
getMethod · 0.65
renderFunction · 0.50

Tested by

no test coverage detected