{
  "cases": [
    {
      "expected": "https://api.deepseek.com/v1/models",
      "fn": "join_api_path",
      "input": {
        "base": "https://api.deepseek.com/v1",
        "path": "models"
      }
    },
    {
      "expected": "https://api.deepseek.com/v1/chat/completions",
      "fn": "join_api_path",
      "input": {
        "base": "https://api.deepseek.com/v1",
        "path": "chat/completions"
      }
    },
    {
      "expected": "https://api.deepseek.com/v1/embeddings",
      "fn": "join_api_path",
      "input": {
        "base": "https://api.deepseek.com/v1",
        "path": "embeddings"
      }
    },
    {
      "expected": "https://api.deepseek.com/v1/models",
      "fn": "join_api_path",
      "input": {
        "base": "https://api.deepseek.com/v1/",
        "path": "models"
      }
    },
    {
      "expected": "https://api.deepseek.com/v1/chat/completions",
      "fn": "join_api_path",
      "input": {
        "base": "https://api.deepseek.com/v1/",
        "path": "chat/completions"
      }
    },
    {
      "expected": "https://api.deepseek.com/v1/embeddings",
      "fn": "join_api_path",
      "input": {
        "base": "https://api.deepseek.com/v1/",
        "path": "embeddings"
      }
    },
    {
      "expected": "https://api.deepseek.com/v1/models",
      "fn": "join_api_path",
      "input": {
        "base": "  https://api.deepseek.com/v1  ",
        "path": "models"
      }
    },
    {
      "expected": "https://api.deepseek.com/v1/chat/completions",
      "fn": "join_api_path",
      "input": {
        "base": "  https://api.deepseek.com/v1  ",
        "path": "chat/completions"
      }
    },
    {
      "expected": "https://api.deepseek.com/v1/embeddings",
      "fn": "join_api_path",
      "input": {
        "base": "  https://api.deepseek.com/v1  ",
        "path": "embeddings"
      }
    },
    {
      "expected": "https://api.deepseek.com/models",
      "fn": "join_api_path",
      "input": {
        "base": "https://api.deepseek.com",
        "path": "models"
      }
    },
    {
      "expected": "https://api.deepseek.com/chat/completions",
      "fn": "join_api_path",
      "input": {
        "base": "https://api.deepseek.com",
        "path": "chat/completions"
      }
    },
    {
      "expected": "https://api.deepseek.com/embeddings",
      "fn": "join_api_path",
      "input": {
        "base": "https://api.deepseek.com",
        "path": "embeddings"
      }
    },
    {
      "expected": "https://open.bigmodel.cn/api/paas/v4/models",
      "fn": "join_api_path",
      "input": {
        "base": "https://open.bigmodel.cn/api/paas/v4",
        "path": "models"
      }
    },
    {
      "expected": "https://open.bigmodel.cn/api/paas/v4/chat/completions",
      "fn": "join_api_path",
      "input": {
        "base": "https://open.bigmodel.cn/api/paas/v4",
        "path": "chat/completions"
      }
    },
    {
      "expected": "https://open.bigmodel.cn/api/paas/v4/embeddings",
      "fn": "join_api_path",
      "input": {
        "base": "https://open.bigmodel.cn/api/paas/v4",
        "path": "embeddings"
      }
    },
    {
      "expected": "https://generativelanguage.googleapis.com/v1beta/openai/models",
      "fn": "join_api_path",
      "input": {
        "base": "https://generativelanguage.googleapis.com/v1beta/openai",
        "path": "models"
      }
    },
    {
      "expected": "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions",
      "fn": "join_api_path",
      "input": {
        "base": "https://generativelanguage.googleapis.com/v1beta/openai",
        "path": "chat/completions"
      }
    },
    {
      "expected": "https://generativelanguage.googleapis.com/v1beta/openai/embeddings",
      "fn": "join_api_path",
      "input": {
        "base": "https://generativelanguage.googleapis.com/v1beta/openai",
        "path": "embeddings"
      }
    },
    {
      "expected": "https://generativelanguage.googleapis.com/v1beta/openai/models",
      "fn": "join_api_path",
      "input": {
        "base": "https://generativelanguage.googleapis.com/v1beta/openai#",
        "path": "models"
      }
    },
    {
      "expected": "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions",
      "fn": "join_api_path",
      "input": {
        "base": "https://generativelanguage.googleapis.com/v1beta/openai#",
        "path": "chat/completions"
      }
    },
    {
      "expected": "https://generativelanguage.googleapis.com/v1beta/openai/embeddings",
      "fn": "join_api_path",
      "input": {
        "base": "https://generativelanguage.googleapis.com/v1beta/openai#",
        "path": "embeddings"
      }
    },
    {
      "expected": "https://proxy.example.com/v1/models",
      "fn": "join_api_path",
      "input": {
        "base": "https://proxy.example.com/v1/chat/completions",
        "path": "models"
      }
    },
    {
      "expected": "https://proxy.example.com/v1/chat/completions",
      "fn": "join_api_path",
      "input": {
        "base": "https://proxy.example.com/v1/chat/completions",
        "path": "chat/completions"
      }
    },
    {
      "expected": "https://proxy.example.com/v1/embeddings",
      "fn": "join_api_path",
      "input": {
        "base": "https://proxy.example.com/v1/chat/completions",
        "path": "embeddings"
      }
    },
    {
      "expected": "https://proxy.example.com/v1/models",
      "fn": "join_api_path",
      "input": {
        "base": "https://proxy.example.com/v1/messages",
        "path": "models"
      }
    },
    {
      "expected": "https://proxy.example.com/v1/chat/completions",
      "fn": "join_api_path",
      "input": {
        "base": "https://proxy.example.com/v1/messages",
        "path": "chat/completions"
      }
    },
    {
      "expected": "https://proxy.example.com/v1/embeddings",
      "fn": "join_api_path",
      "input": {
        "base": "https://proxy.example.com/v1/messages",
        "path": "embeddings"
      }
    },
    {
      "expected": "https://proxy.example.com/v1/completions/models",
      "fn": "join_api_path",
      "input": {
        "base": "https://proxy.example.com/v1/completions",
        "path": "models"
      }
    },
    {
      "expected": "https://proxy.example.com/v1/completions/chat/completions",
      "fn": "join_api_path",
      "input": {
        "base": "https://proxy.example.com/v1/completions",
        "path": "chat/completions"
      }
    },
    {
      "expected": "https://proxy.example.com/v1/completions/embeddings",
      "fn": "join_api_path",
      "input": {
        "base": "https://proxy.example.com/v1/completions",
        "path": "embeddings"
      }
    },
    {
      "expected": "https://proxy.example.com/v1/responses/models",
      "fn": "join_api_path",
      "input": {
        "base": "https://proxy.example.com/v1/responses",
        "path": "models"
      }
    },
    {
      "expected": "https://proxy.example.com/v1/responses/chat/completions",
      "fn": "join_api_path",
      "input": {
        "base": "https://proxy.example.com/v1/responses",
        "path": "chat/completions"
      }
    },
    {
      "expected": "https://proxy.example.com/v1/responses/embeddings",
      "fn": "join_api_path",
      "input": {
        "base": "https://proxy.example.com/v1/responses",
        "path": "embeddings"
      }
    },
    {
      "expected": "https://proxy.example.com/v1/models",
      "fn": "join_api_path",
      "input": {
        "base": "https://proxy.example.com/v1/chat/completions/#",
        "path": "models"
      }
    },
    {
      "expected": "https://proxy.example.com/v1/chat/completions",
      "fn": "join_api_path",
      "input": {
        "base": "https://proxy.example.com/v1/chat/completions/#",
        "path": "chat/completions"
      }
    },
    {
      "expected": "https://proxy.example.com/v1/embeddings",
      "fn": "join_api_path",
      "input": {
        "base": "https://proxy.example.com/v1/chat/completions/#",
        "path": "embeddings"
      }
    },
    {
      "expected": "https://api.deepseek.com/v1/chat/completions",
      "fn": "join_chat_endpoint",
      "input": {
        "base": "https://api.deepseek.com/v1",
        "path": "chat/completions"
      }
    },
    {
      "expected": "https://api.deepseek.com/v1/messages",
      "fn": "join_chat_endpoint",
      "input": {
        "base": "https://api.deepseek.com/v1",
        "path": "messages"
      }
    },
    {
      "expected": "https://api.deepseek.com/chat/completions",
      "fn": "join_chat_endpoint",
      "input": {
        "base": "https://api.deepseek.com",
        "path": "chat/completions"
      }
    },
    {
      "expected": "https://api.deepseek.com/v1/messages",
      "fn": "join_chat_endpoint",
      "input": {
        "base": "https://api.deepseek.com",
        "path": "messages"
      }
    },
    {
      "expected": "https://relay.example.com/v1/chat/completions",
      "fn": "join_chat_endpoint",
      "input": {
        "base": "https://relay.example.com/v1/chat/completions",
        "path": "chat/completions"
      }
    },
    {
      "expected": "https://relay.example.com/v1/messages",
      "fn": "join_chat_endpoint",
      "input": {
        "base": "https://relay.example.com/v1/chat/completions",
        "path": "messages"
      }
    },
    {
      "expected": "https://api.anthropic.com/chat/completions",
      "fn": "join_chat_endpoint",
      "input": {
        "base": "https://api.anthropic.com",
        "path": "chat/completions"
      }
    },
    {
      "expected": "https://api.anthropic.com/v1/messages",
      "fn": "join_chat_endpoint",
      "input": {
        "base": "https://api.anthropic.com",
        "path": "messages"
      }
    },
    {
      "expected": "https://api.anthropic.com/v1/chat/completions",
      "fn": "join_chat_endpoint",
      "input": {
        "base": "https://api.anthropic.com/v1",
        "path": "chat/completions"
      }
    },
    {
      "expected": "https://api.anthropic.com/v1/messages",
      "fn": "join_chat_endpoint",
      "input": {
        "base": "https://api.anthropic.com/v1",
        "path": "messages"
      }
    },
    {
      "expected": "https://cc.example.top:8443/chat/completions",
      "fn": "join_chat_endpoint",
      "input": {
        "base": "https://cc.example.top:8443",
        "path": "chat/completions"
      }
    },
    {
      "expected": "https://cc.example.top:8443/v1/messages",
      "fn": "join_chat_endpoint",
      "input": {
        "base": "https://cc.example.top:8443",
        "path": "messages"
      }
    },
    {
      "expected": "https://api.deepseek.com/anthropic/chat/completions",
      "fn": "join_chat_endpoint",
      "input": {
        "base": "https://api.deepseek.com/anthropic",
        "path": "chat/completions"
      }
    },
    {
      "expected": "https://api.deepseek.com/anthropic/v1/messages",
      "fn": "join_chat_endpoint",
      "input": {
        "base": "https://api.deepseek.com/anthropic",
        "path": "messages"
      }
    },
    {
      "expected": "https://proxy.example.com/v1/chat/completions",
      "fn": "join_chat_endpoint",
      "input": {
        "base": "https://proxy.example.com/v1/messages",
        "path": "chat/completions"
      }
    },
    {
      "expected": "https://proxy.example.com/v1/messages",
      "fn": "join_chat_endpoint",
      "input": {
        "base": "https://proxy.example.com/v1/messages",
        "path": "messages"
      }
    },
    {
      "expected": "https://odd.gateway.com/raw/chat/completions",
      "fn": "join_chat_endpoint",
      "input": {
        "base": "https://odd.gateway.com/raw#",
        "path": "chat/completions"
      }
    },
    {
      "expected": "https://odd.gateway.com/raw/messages",
      "fn": "join_chat_endpoint",
      "input": {
        "base": "https://odd.gateway.com/raw#",
        "path": "messages"
      }
    },
    {
      "expected": "https://odd.gateway.com/raw/chat/completions",
      "fn": "join_chat_endpoint",
      "input": {
        "base": "https://odd.gateway.com/raw/messages#",
        "path": "chat/completions"
      }
    },
    {
      "expected": "https://odd.gateway.com/raw/messages",
      "fn": "join_chat_endpoint",
      "input": {
        "base": "https://odd.gateway.com/raw/messages#",
        "path": "messages"
      }
    },
    {
      "expected": "https://relay.example.com/V1/chat/completions",
      "fn": "join_chat_endpoint",
      "input": {
        "base": "https://relay.example.com/V1",
        "path": "chat/completions"
      }
    },
    {
      "expected": "https://relay.example.com/V1/v1/messages",
      "fn": "join_chat_endpoint",
      "input": {
        "base": "https://relay.example.com/V1",
        "path": "messages"
      }
    },
    {
      "expected": "https://relay.example.com/v1/mymessages/chat/completions",
      "fn": "join_chat_endpoint",
      "input": {
        "base": "https://relay.example.com/v1/mymessages",
        "path": "chat/completions"
      }
    },
    {
      "expected": "https://relay.example.com/v1/mymessages/v1/messages",
      "fn": "join_chat_endpoint",
      "input": {
        "base": "https://relay.example.com/v1/mymessages",
        "path": "messages"
      }
    },
    {
      "expected": "/chat/completions",
      "fn": "join_chat_endpoint",
      "input": {
        "base": "",
        "path": "chat/completions"
      }
    },
    {
      "expected": "/messages",
      "fn": "join_chat_endpoint",
      "input": {
        "base": "",
        "path": "messages"
      }
    },
    {
      "expected": "https://api.deepseek.com/v1",
      "fn": "anthropic_base_url",
      "input": {
        "base": "https://api.deepseek.com/v1"
      }
    },
    {
      "expected": "https://api.deepseek.com/v1",
      "fn": "anthropic_base_url",
      "input": {
        "base": "https://api.deepseek.com"
      }
    },
    {
      "expected": "https://relay.example.com/v1",
      "fn": "anthropic_base_url",
      "input": {
        "base": "https://relay.example.com/v1/chat/completions"
      }
    },
    {
      "expected": "https://api.anthropic.com/v1",
      "fn": "anthropic_base_url",
      "input": {
        "base": "https://api.anthropic.com"
      }
    },
    {
      "expected": "https://api.anthropic.com/v1",
      "fn": "anthropic_base_url",
      "input": {
        "base": "https://api.anthropic.com/v1"
      }
    },
    {
      "expected": "https://cc.example.top:8443/v1",
      "fn": "anthropic_base_url",
      "input": {
        "base": "https://cc.example.top:8443"
      }
    },
    {
      "expected": "https://api.deepseek.com/anthropic/v1",
      "fn": "anthropic_base_url",
      "input": {
        "base": "https://api.deepseek.com/anthropic"
      }
    },
    {
      "expected": "https://proxy.example.com/v1",
      "fn": "anthropic_base_url",
      "input": {
        "base": "https://proxy.example.com/v1/messages"
      }
    },
    {
      "expected": "https://odd.gateway.com/raw",
      "fn": "anthropic_base_url",
      "input": {
        "base": "https://odd.gateway.com/raw#"
      }
    },
    {
      "expected": "https://odd.gateway.com/raw",
      "fn": "anthropic_base_url",
      "input": {
        "base": "https://odd.gateway.com/raw/messages#"
      }
    },
    {
      "expected": "https://relay.example.com/V1/v1",
      "fn": "anthropic_base_url",
      "input": {
        "base": "https://relay.example.com/V1"
      }
    },
    {
      "expected": "https://relay.example.com/v1/mymessages/v1",
      "fn": "anthropic_base_url",
      "input": {
        "base": "https://relay.example.com/v1/mymessages"
      }
    },
    {
      "expected": "",
      "fn": "anthropic_base_url",
      "input": {
        "base": ""
      }
    },
    {
      "expected": true,
      "fn": "ends_with_version_segment",
      "input": {
        "base": "https://api.deepseek.com/v1"
      }
    },
    {
      "expected": true,
      "fn": "ends_with_version_segment",
      "input": {
        "base": "https://api.deepseek.com/v1/"
      }
    },
    {
      "expected": true,
      "fn": "ends_with_version_segment",
      "input": {
        "base": "https://open.bigmodel.cn/api/paas/v4"
      }
    },
    {
      "expected": false,
      "fn": "ends_with_version_segment",
      "input": {
        "base": "https://generativelanguage.googleapis.com/v1beta/openai"
      }
    },
    {
      "expected": false,
      "fn": "ends_with_version_segment",
      "input": {
        "base": "https://x.com/v1beta"
      }
    },
    {
      "expected": false,
      "fn": "ends_with_version_segment",
      "input": {
        "base": "https://api.deepseek.com"
      }
    },
    {
      "expected": false,
      "fn": "ends_with_version_segment",
      "input": {
        "base": "https://v4.example.com"
      }
    },
    {
      "expected": true,
      "fn": "ends_with_version_segment",
      "input": {
        "base": "https://v4"
      }
    },
    {
      "expected": true,
      "fn": "ends_with_version_segment",
      "input": {
        "base": "https://x.com/v1//"
      }
    },
    {
      "expected": false,
      "fn": "ends_with_version_segment",
      "input": {
        "base": "https://x.com/V1"
      }
    },
    {
      "expected": false,
      "fn": "ends_with_version_segment",
      "input": {
        "base": "https://x.com/v"
      }
    },
    {
      "expected": false,
      "fn": "ends_with_version_segment",
      "input": {
        "base": ""
      }
    }
  ],
  "crateVersion": "0.1.2",
  "description": "下文「剥端点后缀」指：若字符串以 /chat/completions 或 /messages 结尾（按路径段匹配，前面必须是 /；区分大小写；按此顺序、只剥一次），去掉该后缀及其前面所有 /。join_api_path(base, path)：去两端空白 → 去末尾所有 # → 去末尾所有 / → 剥端点后缀 → 拼上 \"/\" + path。base 为空时结果是 \"/\" + path —— 空地址不在本函数职责内，调用方应先校验。anthropic_base_url(base)：去两端空白，记下末尾是否有 # → 去末尾所有 # → 去末尾所有 / → 剥端点后缀，得到 b；原来末尾有 #、或 b 为空、或 ends_with_version_segment(b) → 返回 b；否则返回 b + \"/v1\"。join_chat_endpoint(base, path)：去两端空白、去末尾所有 #、去末尾所有 / 后，若以 \"/\" + path 结尾 → 原样返回（只有粘进来的端点与请求的 path 一致时才原样用）；否则 path 为 messages → join_api_path(anthropic_base_url(base), path)；其余 → join_api_path(base, path)。ends_with_version_segment(base)：去两端空白、去末尾所有 / 后，取最后一个 / 之后的部分（不区分它是主机名还是路径，所以 https://v4 也算），它是否为小写 v 后跟至少一位 ASCII 数字；v1beta、V1、单独的 v 都不算。",
  "generatedBy": "cargo xtask gen-spec（期望值由 Rust 参考实现算出，请勿手改）",
  "specVersion": 1,
  "title": "端点拼接"
}
