mirror of https://github.com/openclaw/openclaw.git
diffs: polish viewerBaseUrl validation
This commit is contained in:
parent
071cbbb31e
commit
b140f2e894
|
|
@ -237,6 +237,23 @@ Persistent viewer URL config:
|
|||
- Plugin-owned fallback for returned viewer links when a tool call does not pass `baseUrl`.
|
||||
- Must be `http` or `https`, no query/hash.
|
||||
|
||||
Example:
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
entries: {
|
||||
diffs: {
|
||||
enabled: true,
|
||||
config: {
|
||||
viewerBaseUrl: "https://gateway.example.com/openclaw",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Security config
|
||||
|
||||
- `security.allowRemoteViewer` (`boolean`, default `false`)
|
||||
|
|
|
|||
|
|
@ -112,6 +112,23 @@ Security options:
|
|||
- `security.allowRemoteViewer` (default `false`): allows non-loopback access to `/plugins/diffs/view/...` token URLs
|
||||
- `viewerBaseUrl` (optional): persistent viewer-link origin/path fallback for shareable URLs
|
||||
|
||||
Example:
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
entries: {
|
||||
diffs: {
|
||||
enabled: true,
|
||||
config: {
|
||||
viewerBaseUrl: "https://gateway.example.com/openclaw",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Example Agent Prompts
|
||||
|
||||
Open in canvas:
|
||||
|
|
|
|||
|
|
@ -305,7 +305,7 @@ describe("diffs plugin schema surfaces", () => {
|
|||
issues: [
|
||||
{
|
||||
path: ["viewerBaseUrl"],
|
||||
message: "baseUrl must use http or https: javascript:alert(1)",
|
||||
message: "viewerBaseUrl must use http or https: javascript:alert(1)",
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -382,6 +382,12 @@ describe("diffs viewer URL helpers", () => {
|
|||
"baseUrl must not include query/hash",
|
||||
);
|
||||
});
|
||||
|
||||
it("uses the configured field name in viewerBaseUrl validation errors", () => {
|
||||
expect(() => normalizeViewerBaseUrl("https://example.com?a=1", "viewerBaseUrl")).toThrow(
|
||||
"viewerBaseUrl must not include query/hash",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("renderDiffDocument", () => {
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ const DiffsPluginJsonSchemaSource = z.strictObject({
|
|||
.string()
|
||||
.superRefine((value, ctx) => {
|
||||
try {
|
||||
normalizeViewerBaseUrl(value);
|
||||
normalizeViewerBaseUrl(value, "viewerBaseUrl");
|
||||
} catch (error) {
|
||||
ctx.addIssue({
|
||||
code: "custom",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import type { OpenClawConfig } from "../api.js";
|
||||
|
||||
const DEFAULT_GATEWAY_PORT = 18789;
|
||||
type ViewerBaseUrlFieldName = "baseUrl" | "viewerBaseUrl";
|
||||
|
||||
export function buildViewerUrl(params: {
|
||||
config: OpenClawConfig;
|
||||
|
|
@ -20,18 +21,21 @@ export function buildViewerUrl(params: {
|
|||
return parsedBase.toString();
|
||||
}
|
||||
|
||||
export function normalizeViewerBaseUrl(raw: string): string {
|
||||
export function normalizeViewerBaseUrl(
|
||||
raw: string,
|
||||
fieldName: ViewerBaseUrlFieldName = "baseUrl",
|
||||
): string {
|
||||
let parsed: URL;
|
||||
try {
|
||||
parsed = new URL(raw);
|
||||
} catch {
|
||||
throw new Error(`Invalid baseUrl: ${raw}`);
|
||||
throw new Error(`Invalid ${fieldName}: ${raw}`);
|
||||
}
|
||||
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
||||
throw new Error(`baseUrl must use http or https: ${raw}`);
|
||||
throw new Error(`${fieldName} must use http or https: ${raw}`);
|
||||
}
|
||||
if (parsed.search || parsed.hash) {
|
||||
throw new Error(`baseUrl must not include query/hash: ${raw}`);
|
||||
throw new Error(`${fieldName} must not include query/hash: ${raw}`);
|
||||
}
|
||||
parsed.search = "";
|
||||
parsed.hash = "";
|
||||
|
|
|
|||
Loading…
Reference in New Issue