BigPizzaV3/CodexPlusPlus · error

API 地址须使用 HTTPS,且不含账号、密码、查询参数或片段

Error message

API 地址须使用 HTTPS,且不含账号、密码、查询参数或片段

What it means

apiEndpoint() accepts only https: URLs and additionally rejects URLs that embed credentials (username/password), query strings (?...), or fragments (#...). This prevents leaking secrets via the URL and guarantees a deterministic endpoint path. It throws this error for any http:// URL or URL containing those components.

Solutions

  1. Use https:// instead of http:// (put the service behind TLS or use a TLS-terminating reverse proxy)
  2. Move the API key out of the URL into the key/password field — the code appends the key as a bearer credential, not a query param
  3. Remove ?query=... and #fragment parts from the URL
  4. Remove user:password@ from the URL

Example fix

// before
apiEndpoint('http://localhost:8080/v1?key=abc')
// after
apiEndpoint('https://my-tls-proxy.example.com/v1') // key goes in the API Key field
Defensive patterns

Strategy: validation

Validate before calling

function checkUrl(raw) {
  try {
    const u = new URL(String(raw).trim());
    if (u.protocol !== 'https:') return 'must be https://';
    if (u.username || u.password) return 'remove credentials from URL';
    if (u.search || u.hash) return 'remove ?query and #fragment';
    return null;
  } catch { return 'not a valid absolute URL'; }
}

Type guard

function isCleanHttpsUrl(u) { return u instanceof URL && u.protocol === 'https:' && !u.username && !u.password && !u.search && !u.hash; }

Try / catch

let endpoint;
try { endpoint = apiEndpoint(raw); } catch (e) { if (String(e).includes('HTTPS')) { showTlsGuidance(); } return; }

Prevention

When it happens

Trigger: apiEndpoint('http://api.example.com/v1'); a URL like https://user:pass@host/v1; URLs with ?api-key=... or #section; any of these after successful URL parsing.

Common situations: User configures a local HTTP-only proxy (http://localhost:11434/v1); user pastes a URL that already includes an API key as a query parameter; user includes credentials in the URL instead of the API Key field.

Understand the failure class

Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.

Related errors


AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19). Data as JSON: /api/errors/d7d2131be1bd703a. Report an issue: GitHub.

Appendix: source

Thrown at tools/conversation-canvas/external-api.mjs:4

// OpenAI-compatible Chat Completions. Never persist credentials in tree checkpoints.
export function apiEndpoint(raw){
  let url;try{url=new URL(String(raw).trim());}catch{throw Error('请输入完整的 HTTPS API 地址');}
  if(url.protocol!=='https:'||url.username||url.password||url.search||url.hash)throw Error('API 地址须使用 HTTPS,且不含账号、密码、查询参数或片段');
  const path=url.pathname.replace(/\/+$/,'');
  url.pathname=path.endsWith('/chat/completions')?path:(path||'/v1')+'/chat/completions';
  return url.href;
}

export function apiConfig(input){
  const channel=input?.channel==='external'?'external':'native';
  const value={channel,baseUrl:String(input?.baseUrl||'').trim(),model:String(input?.model||'').trim(),key:String(input?.key||'').trim(),remember:input?.remember===true,speed:input?.speed==='provider'?'provider':'fast',revision:input?.revision||crypto.randomUUID()};
  if(channel==='external'){
    value.endpoint=apiEndpoint(value.baseUrl);
    if(!value.model||value.model.length>200)throw Error('请填写 API 的模型名称');
    if(!value.key||/[\r\n]/.test(value.key))throw Error('请在设置中填写有效 API Key');
  }
  return value;
}

export function storedApiConfig(config){
  const {channel,baseUrl,model,remember,speed,revision}=config;

View on GitHub (pinned to b1ed92e5e4)