1

A colleague recommended I repost this from StackOverflow to ServerFault:

This has been driving me crazy. I have a web application that's being served via Apache Web Server. The database server that backs the application is Apache CouchDB, which exposes an HTTP API to retrieve documents and stream attachments.

I've secured the CouchDB database by providing a security object, which only allows certain users to access data within the database, and returns 401 for anonymous requests to HTTP endpoints.

I want to be able to map public URLs to document attachments stored within this database. So, I've attempted to create a rewrite rule inside my .htaccess file that proxies requests from certain URLs directly to CouchDB, while hardcoding the user credentials, like so:

## DOWNLOAD STREAM:
RewriteCond %{HTTP_HOST} ^example.com$
RewriteRule download/(.*) http://user:pass@127.0.0.1:5984/database/$1 [P]

In an ideal world, the above example would take the following URL:

http://example.com/download/UUID/attachment.ext

And proxy it to:

http://user:pass@127.0.0.1:5984/database/UUID/attachment.ext

This method does indeed proxy the request to CouchDB, but omits the userinfo component of the URI scheme. So, the request is treated as anonymous and I get a 401 error. The attachment is only streamed if I remove security from the database.

I've spent a couple of hours reading up on Apache configuration and experimenting to no avail. Web searches are fruitless because of all the related queries with similar keywords.

How can I ensure that mod_rewrite includes the username and password provided in the rewrite rule when it proxies to CouchDB?

1

I figured it out! Rather than including the username:password as part of the URI scheme, the Authorization header needs to be set independently. The following solution works completely within a .htaccess file, which is important since OS X periodically blows away settings inside VirtualHost sites:

SetEnvIf Request_URI ^/download/* ADD_COUCH_BASIC_AUTH
RequestHeader set Authorization "Basic XXXXXXXXXXXX" env=ADD_COUCH_BASIC_AUTH

## DOWNLOAD STREAM
RewriteCond %{HTTP_HOST} ^example.com$
RewriteRule download/(.*) http://127.0.0.1:5984/database/$1 [P]

The way this works: we use SetEnvIf to check whether the request path matches the path we want to proxy, and if so, set an arbitrary environment variable ADD_COUCH_BASIC_AUTH

On the subsequent line, we add a Basic Auth header to the outgoing request, only if the environment variable we set exists. So, the basic auth header will only be added when requesting a resource via /download/, thus sending authentication credentials to CouchDB.

Note: you'll have to Base64-encode your username:password credentials, and replace XXXXXXXXXXX with the encoded value. An easy way to do this, on a Mac:

echo -n 'user:pass' | openssl base64

Hope this helps somebody besides me!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.