Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTTP OPTIONS method not allowed for _users database in CouchDB

I'm trying to change a user's password from within an application that connects to CouchDB from another domain. My code is more or less the same as the example in the CouchDB Docs, i.e. get the document, change the data, then send a PUT request back with the changes. The issue is occurring with the PUT request - because of CORS the browser tries to do an OPTIONS request before sending the PUT request, but the OPTIONS request is returning 405 Method Not Allowed.

Does anyone have an idea of how to get around this?

Here's the request headers in case it's helpful:

OPTIONS /_users/org.couchdb.user:clinic_admin HTTP/1.1
Host: localhost:15984
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Access-Control-Request-Method: PUT
Origin: https://localhost:15000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36
Access-Control-Request-Headers: content-type, if-match
Accept: */*
Referer: https://localhost:15000/webapp/
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8,ja;q=0.6,sv;q=0.4,zh-CN;q=0.2
like image 255
Luke Hansford Avatar asked Dec 19 '22 00:12

Luke Hansford


1 Answers

There are two options here. I prefer option #2 but I'll start with #1.

Option 1: configure CORS correctly

Often 405 errors in CouchDB are due to misconfigurations, e.g. not including all the possible headers and methods, of which there are a lot if you want to support all browsers/devices.

On the PouchDB team we've gathered the "best practices" together into a single module: add-cors-to-couchdb, which should work for both CouchDB 1.6.1 and CouchDB 2.0. Just run:

npm install --global add-cors-to-couchdb
add-cors-to-couchdb http://example.com:5984 -u admin_username -p admin_password

This should fix your problem; if not, check out the tests for PouchDB or for pouchdb-authentication which successfully use this method to test against a database running at localhost:5984 (including changing a user's password, which is what you're trying to do).

Option 2: avoid CORS using a reverse proxy

This is really the best option. It's better for a few reasons:

  1. Spend a couple minutes configuring Apache/nginx to avoid CORS altogether, save yourself headaches later trying to get CORS to work correctly
  2. CORS is less performant than no-CORS because the browser needs to do preflight OPTIONS requests, which add extra latency especially during replication
  3. This is also easier in mobile hybrid apps; Cordova has a one-liner option to whitelist certain domains and avoid CORS.

I typically use the Nginx as a reverse proxy guide for CouchDB and route to a database running at example.com/couchdb. E.g.:

location /couchdb {
    rewrite /couchdb/(.*) /$1 break;
    proxy_pass http://localhost:5984;
    proxy_redirect off;
    proxy_buffering off;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

Note that this may break /_utils (Futon/Fauxton), but the best bet in those cases is to set up a reverse tunnel to your server via SSH and look at it locally:

ssh -L3000:localhost:5984 [email protected]
# now open localhost:3000/_utils in a browser

You probably don't want Futon/Fauxton exposed to the world anyway.

The advantages here are that you can block off certain methods or certain parts of CouchDB using Nginx/Apache, which is typically more flexible than the HTTP options available in CouchDB.

like image 52
nlawson Avatar answered Feb 12 '23 11:02

nlawson