4.2. Document submission using HTML Forms¶
It is possible to write to a CouchDB document directly from an HTML form by using a document update function. Here’s how:
4.2.1. The HTML form¶
First, write an HTML form. Here’s a simple “Contact Us” form excerpt:
<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>
Customize the /dbname/_design/ddocname/_update/contactform
portion of the
form action URL to reflect the exact path to your database, design document
and update function (see below).
As CouchDB
no longer recommends the use of CouchDB-hosted web applications
, you may want to use a reverse proxy to expose CouchDB as a subdirectory of
your web application. If so, add that prefix to the action
destination in
the form.
Another option is to alter CouchDB’s CORS settings and use a cross-domain POST. Be sure you understand all security implications before doing this!
4.2.2. The update function¶
Then, write an update function. This is the server-side JavaScript function
that will receive the POST
-ed data.
The first argument to the function will be the document that is being processed
(if it exists). Because we are using POST
and not PUT
, this should be
empty in our scenario - but we should check to be sure. The POST
-ed data
will be passed as the second parameter to the function, along with any query
parameters and the full request headers.
Here’s a sample handler that extracts the form data, generates a document _id based on the email address and timestamp, and saves the document. It then returns a JSON success response back to the browser.
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"})]
}
Place the above function in your design document under the updates
key.
Note that this function does not attempt any sort of input validation or sanitization. That is best handled by a validate document update function instead. (A “VDU” will validate any document written to the database, not just those that use your update function.)
If the first element passed to return
is a document, the HTTP response
headers will include X-Couch-Id
, the _id
value for the newly created
document, and X-Couch-Update-NewRev
, the _rev
value for the newly
created document. This is handy if your client-side code wants to access or
update the document in a future call.
4.2.3. Example output¶
Here’s the worked sample above, using curl
to simulate the form POST.
$ curl -X PUT adm:pass@localhost:5984/testdb/_design/myddoc -d '{ "updates": { "contactform": "function(doc, req) { ... }" } }'
{"ok":true,"id":"_design/myddoc","rev":"1-2a2b0951fcaf7287817573b03bba02ed"}
$ curl --data "name=Lin&email=lin@example.com&message=I Love CouchDB" http://adm:pass@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://adm:pass@localhost:5984/testdb/lin\@example.com_2018-04-05T19:51:22.278Z
{"_id":"lin@example.com_2018-04-05T19:51:22.278Z","_rev":"1-34483732407fcc6cfc5b60ace48b9da9","name":"Lin","email":"lin@example.com","message":"I Love CouchDB"}