4.2. 使用 HTML 表单提交文档

可以使用文档 更新函数 直接从 HTML 表单写入 CouchDB 文档。以下是操作方法

4.2.1. HTML 表单

首先,编写一个 HTML 表单。以下是一个简单的“联系我们”表单摘录

<form action="/dbname/_design/ddocname/_update/contactform" method="post">
    <div>
        <label for="name">Name:</label>
        <input type="text" id="name" name="name" />
    </div>
    <div>
        <label for="mail">Email:</label>
        <input type="text" id="mail" name="email" />
    </div>
    <div>
        <label for="msg">Message:</label>
        <textarea id="msg" name="message"></textarea>
    </div>
</form>

自定义表单操作 URL 中的 /dbname/_design/ddocname/_update/contactform 部分,以反映数据库、设计文档和更新函数的准确路径(见下文)。

由于 CouchDB 不再推荐使用 CouchDB 托管的 Web 应用程序,您可能希望使用反向代理将 CouchDB 作为 Web 应用程序的子目录公开。如果是这样,请将该前缀添加到表单中的 action 目标。

另一种选择是更改 CouchDB 的 CORS 设置并使用跨域 POST。在执行此操作之前,请确保您了解所有安全隐患!

4.2.2. 更新函数

然后,编写一个更新函数。这是接收 POST 数据的服务器端 JavaScript 函数。

函数的第一个参数将是正在处理的文档(如果存在)。因为我们使用的是 POST 而不是 PUT,所以这种情况应该为空 - 但我们应该检查以确保。 POST 数据将作为函数的第二个参数传递,以及任何查询参数和完整的请求头。

以下是一个示例处理程序,它提取表单数据,根据电子邮件地址和时间戳生成文档 _id,并保存文档。然后,它将 JSON 成功响应返回到浏览器。

function(doc, req) {

    if (doc) {
        return [doc, toJSON({"error": "request already filed"})]
    }

    if !(req.form && req.form.email) {
        return [null, toJSON({"error": "incomplete form"})]
    }

    var date = new Date()
    var newdoc = req.form
    newdoc._id = req.form.email + "_" + date.toISOString()

    return [newdoc, toJSON({"success":"ok"})]
}

将上述函数放在设计文档的 updates 键下。

请注意,此函数不会尝试进行任何类型的输入验证或清理。最好由 验证文档更新函数 处理。(“VDU”将验证写入数据库的任何文档,而不仅仅是使用更新函数的文档。)

如果传递给 return 的第一个元素是文档,则 HTTP 响应头将包含 X-Couch-Id(新创建文档的 _id 值)和 X-Couch-Update-NewRev(新创建文档的 _rev 值)。这在您的客户端代码想要在将来的调用中访问或更新文档时非常有用。

4.2.3. 示例输出

以下是使用 curl 模拟表单 POST 的上述示例。

$ curl -X PUT localhost:5984/testdb/_design/myddoc -d '{ "updates": { "contactform": "function(doc, req) { ... }" } }'
{"ok":true,"id":"_design/myddoc","rev":"1-2a2b0951fcaf7287817573b03bba02ed"}

$ curl --data "name=Lin&[email protected]&message=I Love CouchDB" http://localhost:5984/testdb/_design/myddoc/_update/contactform
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 5984 (#1)
> POST /testdb/_design/myddoc/_update/contactform HTTP/1.1
> Host: localhost:5984
> User-Agent: curl/7.59.0
> Accept: */*
> Content-Length: 53
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 53 out of 53 bytes
< HTTP/1.1 201 Created
< Content-Length: 16
< Content-Type: text/html; charset=utf-8
< Date: Thu, 05 Apr 2018 19:56:42 GMT
< Server: CouchDB/2.2.0-948a1311c (Erlang OTP/19)
< X-Couch-Id: lin%40example.com_2018-04-05T19:51:22.278Z
< X-Couch-Request-ID: 03a5f4fbe0
< X-Couch-Update-NewRev: 1-34483732407fcc6cfc5b60ace48b9da9
< X-CouchDB-Body-Time: 0
<
* Connection #1 to host localhost left intact
{"success":"ok"}

$ curl http://localhost:5984/testdb/lin\@example.com_2018-04-05T19:51:22.278Z
{"_id":"[email protected]_2018-04-05T19:51:22.278Z","_rev":"1-34483732407fcc6cfc5b60ace48b9da9","name":"Lin","email":"[email protected]","message":"I Love CouchDB"}