feat(searxng): configure endpoint via SEARXNG_URL env (#2499)
Add SEARXNG_URL runtime override for the built-in SearXNG web-search provider, defaulting to http://localhost:8888/search. Enables Docker and remote SearXNG deployments without changing existing behavior. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -34,5 +34,8 @@ NEXT_PUBLIC_CLOUD_URL=https://9router.com
|
||||
# ALL_PROXY=socks5://127.0.0.1:7890
|
||||
# NO_PROXY=localhost,127.0.0.1
|
||||
|
||||
# Optional SearXNG endpoint for the built-in unauthenticated web-search provider.
|
||||
# SEARXNG_URL=http://searxng:8080/search
|
||||
|
||||
# Currently unused by application runtime (kept as reference)
|
||||
# INSTANCE_NAME=9router
|
||||
|
||||
@@ -1220,6 +1220,7 @@ docker pull decolua/9router:latest # update to latest
|
||||
| `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (set `true` behind HTTPS reverse proxy) |
|
||||
| `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` routes (recommended for internet-exposed deploys) |
|
||||
| `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` | empty | Optional outbound proxy for upstream provider calls |
|
||||
| `SEARXNG_URL` | `http://localhost:8888/search` | Endpoint for the built-in unauthenticated SearXNG web-search provider |
|
||||
|
||||
Notes:
|
||||
|
||||
|
||||
@@ -39,6 +39,15 @@ function envMs(name, def) {
|
||||
return Number.isFinite(n) && n > 0 ? n : def;
|
||||
}
|
||||
|
||||
function envUrl(name, def) {
|
||||
const raw = process.env[name]?.trim();
|
||||
return raw || def;
|
||||
}
|
||||
|
||||
// SearXNG endpoint used by the unauthenticated web-search provider.
|
||||
// Configure this for a separate Docker service or remote SearXNG instance.
|
||||
export const SEARXNG_URL = envUrl("SEARXNG_URL", "http://localhost:8888/search");
|
||||
|
||||
// Inter-chunk stall timeout (once tokens are flowing). Generous headroom so
|
||||
// slow reasoning models aren't aborted mid-stream. Env: STREAM_STALL_TIMEOUT_MS.
|
||||
export const STREAM_STALL_TIMEOUT_MS = envMs("STREAM_STALL_TIMEOUT_MS", 360 * 1000);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { SEARXNG_URL } from "../../config/runtimeConfig.js";
|
||||
|
||||
export default {
|
||||
id: "searxng",
|
||||
alias: "searxng",
|
||||
@@ -15,7 +17,7 @@ export default {
|
||||
],
|
||||
noAuth: true,
|
||||
searchConfig: {
|
||||
baseUrl: "http://localhost:8888/search",
|
||||
baseUrl: SEARXNG_URL,
|
||||
method: "GET",
|
||||
authType: "none",
|
||||
authHeader: "none",
|
||||
|
||||
30
tests/unit/searxng-provider-config.test.js
Normal file
30
tests/unit/searxng-provider-config.test.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const originalSearxngUrl = process.env.SEARXNG_URL;
|
||||
|
||||
async function loadProvider(url) {
|
||||
if (url === undefined) delete process.env.SEARXNG_URL;
|
||||
else process.env.SEARXNG_URL = url;
|
||||
vi.resetModules();
|
||||
return (await import("../../open-sse/providers/registry/searxng.js")).default;
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
if (originalSearxngUrl === undefined) delete process.env.SEARXNG_URL;
|
||||
else process.env.SEARXNG_URL = originalSearxngUrl;
|
||||
vi.resetModules();
|
||||
});
|
||||
|
||||
describe("SearXNG provider configuration", () => {
|
||||
it("uses SEARXNG_URL when the deployment config supplies one", async () => {
|
||||
const provider = await loadProvider("http://searxng:8080/search");
|
||||
|
||||
expect(provider.searchConfig.baseUrl).toBe("http://searxng:8080/search");
|
||||
});
|
||||
|
||||
it("preserves the loopback default when SEARXNG_URL is unset", async () => {
|
||||
const provider = await loadProvider(undefined);
|
||||
|
||||
expect(provider.searchConfig.baseUrl).toBe("http://localhost:8888/search");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user