mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-21 14:11:26 +00:00
* gateway: ignore bearer-declared HTTP operator scopes * gateway: key HTTP bearer guards to auth mode * gateway: refresh rebased HTTP regression expectations * gateway: honor resolved HTTP auth method * gateway: remove duplicate openresponses owner flags
72 lines
2.1 KiB
TypeScript
72 lines
2.1 KiB
TypeScript
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
import type { AuthRateLimiter } from "./auth-rate-limit.js";
|
|
import type { ResolvedGatewayAuth } from "./auth.js";
|
|
import { readJsonBodyOrError, sendJson, sendMethodNotAllowed } from "./http-common.js";
|
|
import {
|
|
authorizeGatewayHttpRequestOrReply,
|
|
type AuthorizedGatewayHttpRequest,
|
|
resolveTrustedHttpOperatorScopes,
|
|
} from "./http-utils.js";
|
|
import { authorizeOperatorScopesForMethod } from "./method-scopes.js";
|
|
|
|
export async function handleGatewayPostJsonEndpoint(
|
|
req: IncomingMessage,
|
|
res: ServerResponse,
|
|
opts: {
|
|
pathname: string;
|
|
auth: ResolvedGatewayAuth;
|
|
maxBodyBytes: number;
|
|
trustedProxies?: string[];
|
|
allowRealIpFallback?: boolean;
|
|
rateLimiter?: AuthRateLimiter;
|
|
requiredOperatorMethod?: "chat.send" | (string & Record<never, never>);
|
|
},
|
|
): Promise<false | { body: unknown; requestAuth: AuthorizedGatewayHttpRequest } | undefined> {
|
|
const url = new URL(req.url ?? "/", `http://${req.headers.host || "localhost"}`);
|
|
if (url.pathname !== opts.pathname) {
|
|
return false;
|
|
}
|
|
|
|
if (req.method !== "POST") {
|
|
sendMethodNotAllowed(res);
|
|
return undefined;
|
|
}
|
|
|
|
const requestAuth = await authorizeGatewayHttpRequestOrReply({
|
|
req,
|
|
res,
|
|
auth: opts.auth,
|
|
trustedProxies: opts.trustedProxies,
|
|
allowRealIpFallback: opts.allowRealIpFallback,
|
|
rateLimiter: opts.rateLimiter,
|
|
});
|
|
if (!requestAuth) {
|
|
return undefined;
|
|
}
|
|
|
|
if (opts.requiredOperatorMethod) {
|
|
const requestedScopes = resolveTrustedHttpOperatorScopes(req, requestAuth);
|
|
const scopeAuth = authorizeOperatorScopesForMethod(
|
|
opts.requiredOperatorMethod,
|
|
requestedScopes,
|
|
);
|
|
if (!scopeAuth.allowed) {
|
|
sendJson(res, 403, {
|
|
ok: false,
|
|
error: {
|
|
type: "forbidden",
|
|
message: `missing scope: ${scopeAuth.missingScope}`,
|
|
},
|
|
});
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
const body = await readJsonBodyOrError(req, res, opts.maxBodyBytes);
|
|
if (body === undefined) {
|
|
return undefined;
|
|
}
|
|
|
|
return { body, requestAuth };
|
|
}
|