1.5.13. /db/_design/design-doc/_rewrite/path

警告

重写功能在 CouchDB 3.0 中已弃用,将在 CouchDB 4.0 中移除。

ANY /{db}/_design/{ddoc}/_rewrite/{path}

根据指定设计文档中定义的规则重写指定路径。重写规则由设计文档的 rewrites 字段定义。 rewrites 字段可以是包含重写函数的字符串,也可以是规则定义的数组

1.5.13.1. 使用字符串化的函数来定义 rewrites

版本 2.0 中的新增功能: rewrites 字段是字符串化的函数时,查询服务器将用于预处理和路由请求。

该函数接受一个 Request2 对象

函数的返回值将导致服务器将请求重写到新位置,或立即返回响应。

要重写请求,请返回包含以下属性的对象

  • path (字符串): 重写后的路径。

  • query (数组): 重写后的查询。如果省略,则使用原始查询键。

  • headers (对象): 重写后的标头。如果省略,则使用原始请求标头。

  • method (字符串): 重写请求的 HTTP 方法 ("GET", "POST" 等)。如果省略,则使用原始请求方法。

  • body (字符串): "POST"/"PUT" 请求的主体。如果省略,则使用原始请求主体。

要立即响应请求,请返回包含以下属性的对象

  • code (数字): 返回的 HTTP 状态码 (200, 404 等)。

  • body (字符串): 返回给用户的响应主体。

示例 A. 限制访问。

function(req2) {
  var path = req2.path.slice(4),
    isWrite = /^(put|post|delete)$/i.test(req2.method),
    isFinance = req2.userCtx.roles.indexOf("finance") > -1;
  if (path[0] == "finance" && isWrite && !isFinance) {
    // Deny writes to  DB "finance" for users
    // having no "finance" role
    return {
      code: 403,
      body: JSON.stringify({
        error: "forbidden".
        reason: "You are not allowed to modify docs in this DB"
      })
    };
  }
  // Pass through all other requests
  return { path: "../../../" + path.join("/") };
}

示例 B. 对 JSON 和 HTML 请求返回不同的回复。

function(req2) {
  var path = req2.path.slice(4),
    h = headers,
    wantsJson = (h.Accept || "").indexOf("application/json") > -1,
    reply = {};
  if (!wantsJson) {
    // Here we should prepare reply object
    // for plain HTML pages
  } else {
    // Pass through JSON requests
    reply.path = "../../../"+path.join("/");
  }
  return reply;
}

1.5.13.2. 使用规则数组来定义 rewrites

rewrites 字段是规则对象的数组时,服务器将根据数组中第一个匹配的规则重写请求。

数组中的每个规则都是一个对象,包含以下字段

  • method (字符串): 将请求方法绑定到规则的 HTTP 请求方法。如果省略,则使用 "*",它匹配所有方法。

  • from (字符串): 用于与 URL 进行比较并定义动态变量的模式。

  • to (字符串): 将 URL 重写到的路径。它可以包含变量,具体取决于在模式匹配期间发现的绑定变量和查询参数(URL 参数和来自 query 成员的参数)。

  • query (对象): 传递给重写 URL 的查询参数。它们可能包含动态变量。

tofrom 路径可能包含以 :* 字符开头的字符串模式,以在匹配中定义动态变量。

rewrites 数组中第一个与传入请求匹配的规则将用于定义重写。要匹配传入请求,规则的 method 必须与请求的 HTTP 方法匹配,并且规则的 from 必须使用以下模式匹配逻辑与请求的路径匹配。

  • 首先,from 模式和 URL 在 / 上分割,以获取令牌列表。例如,如果 from 字段是 /somepath/:var/* 并且 URL 是 /somepath/a/b/c,则 from 模式的令牌为 somepath, :var*,而 URL 的令牌为 somepath, a, bc

  • 模式中以 : 开头的每个令牌将匹配 URL 中的对应令牌,并定义一个新的动态变量,其名称是 : 之后剩余的字符串,其值为来自 URL 的令牌。在本例中,:var 令牌将匹配 b 并设置 var = a

  • 模式中的星号令牌 * 将匹配 URL 中的任意数量的令牌,并且必须是模式中的最后一个令牌。它将定义一个动态变量,其值为剩余的令牌。在本例中,* 令牌将匹配 bc 令牌,并设置 * = b/c

  • 剩余的令牌必须完全匹配,才能使模式被视为匹配。在本例中,模式中的 somepath 匹配 URL 中的 somepath,并且 URL 中的所有令牌都已匹配,导致此规则匹配。

找到规则后,将使用 toquery 字段重写请求 URL。动态变量将被替换到这些字段中的 :* 变量中,以生成最终的 URL。

如果没有任何规则匹配,则返回 404 Not Found 响应。

示例

规则

URL

重写为

令牌

{“from”: “/a”,

“to”: “/some”}

/a

/some

{“from”: “/a/*”,

“to”: “/some/*}

/a/b/c

/some/b/c

{“from”: “/a/b”,

“to”: “/some”}

/a/b?k=v

/some?k=v

k=v

{“from”: “/a/b”,

“to”: “/some/:var”}

/a/b

/some/b?var=b

var=b

{“from”: “/a/:foo/”,

“to”: “/some/:foo/”}

/a/b/c

/some/b/c?foo=b

foo=b

{“from”: “/a/:foo”,

“to”: “/some”, “query”: { “k”: “:foo” }}

/a/b

/some/?k=b&foo=b

foo=b

{“from”: “/a”,

“to”: “/some/:foo”}

/a?foo=b

/some/?b&foo=b

foo=b

请求方法、头信息、查询参数、请求负载和响应主体取决于 URL 将被重写的端点。

param db:

数据库名称

param ddoc:

设计文档名称

param path:

要重写的 URL 路径