The solution I shared doesn't use send_data. Here is a quick review of what's being done in my merb app:
# This is the code handling couchdb attachment
# all urls must be prepended by /assets/
# the router can run some auth/logging etc...
# and instruct nginx to serve the file directly from couchdb
#
match("/assets/:db/:doc_id/:filename(.:ext)").defer_to do |request, params|
filename = CGI.escape "#{params[:filename]}#{params[:ext] ? ".#{params[:ext]}" : ''}"
doc_uri = "#{params[:db]}/#{params[:doc_id]}/#{filename}"
case Merb.environment
when /production|staging/
# TODO protect access to some DBs + auth access (check session, HTTP query, auth etc..)
header = {}
header['Content-Type'] = 'application/octet-stream' # We could also load the doc stub to get the real content-type
header['Content-Disposition'] = "inline; filename=#{filename}"
header['X-Accel-Redirect'] = "/couch/#{doc_uri}"
[200, header, ""]
else
redirect "#{DB.uri}/#{doc_uri}"
end
end
CouchDB is setup as follows:
location /couch/ {
internal;
}
As you see, everything is transparent in the app itself. In the case of your proxy, you are basically opening the entire DB to anyone. You could probably start by limiting to only GET access but you won't have any control over who can see what document. Our previous solution was limiting access using the same type of rewrite you did but with db limitation and file format restrictions. The problem is that you still can't easily limit or log accesses to the assets. You also have another major issue: such a setup won't work in a development/test mode if you don't use nginx.
Basically, using Merb's router + nginx you get full control over who can access what and how. Plus logging capabilities etc.. all that, almost for free since the router is super fast and you are not dispatching any requests.
I hope it helps,
- Matt