Skip to content

Instantly share code, notes, and snippets.

@pokstad
Last active August 29, 2015 14:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pokstad/b74b572844d7f9521716 to your computer and use it in GitHub Desktop.
Save pokstad/b74b572844d7f9521716 to your computer and use it in GitHub Desktop.
CouchDB Reverse Proxy in Go
package main
import (
"net/http"
"net/url"
"net/http/httputil"
"github.com/pokstad/go-couchdb/couchdaemon"
"github.com/pokstad/go-couchdb"
"time"
"sync"
)
var logger couchdaemon.LogWriter
var server_configs = map[string]string{
"username":"username_goes_here", // optional, provide credentials through local.ini
"password":"password_goes_here", // optional, provide credentials through local.ini
"couchURL":"http://localhost:5984", // optional
"static_web_assets":"/www/public", // static files
"http_port":":8080", // only root can run port 80
"ssl_port":":4433", // only root can run port 443
"public_key":"/ssl/server.crt", // If you want SSL...
"private_key":"/ssl/server.key", // If you want SSL...
}
func fetchCouchdbConfigs() {
fetched_configs, err := couchdaemon.ConfigSection("go_server")
if err != nil {
logger.Err(err)
panic(err)
}
for k, v := range fetched_configs {
// overwrite values in default_configs with ones we received from CouchDB
server_configs[k] = v
}
logger.Debug(server_configs)
}
func customAPI(rw http.ResponseWriter, req *http.Request) {
// your middleware lives here
}
func main() {
couchdaemon.Init(nil)
logger = couchdaemon.NewLogWriter()
fetchCouchdbConfigs()
logger.Debug("Server starting")
couchServer, err := couchdb.NewClient(server_configs["couchURL"], nil)
if err != nil {
logger.Err(err)
panic(err)
}
couchAuth := couchdb.BasicAuth(server_configs["username"], server_configs["password"])
couchServer.SetAuth(couchAuth)
mux := http.NewServeMux()
// by default, URL's will be mapped to our static assets
mux.Handle("/",
http.FileServer(http.Dir(server_configs["static_web_assets"])))
// create a reverse proxy to our couch server
proxy_url, _ := url.Parse(server_configs["couchURL"])
mux.Handle("/db/",
http.StripPrefix("/db/",
httputil.NewSingleHostReverseProxy(proxy_url)))
mux.HandleFunc("/api", customAPI)
http_serv := &http.Server{
Addr: server_configs["http_port"],
Handler: mux,
ReadTimeout:30*time.Second, // helps kill ghost Goroutines:
// http://stackoverflow.com/questions/10971800/golang-http-server-leaving-open-goroutines
//ErrorLog: nil, // suppresses errors from stderr
}
http_ssl_serv := &http.Server{
Addr: server_configs["ssl_port"],
Handler: mux,
ReadTimeout:30*time.Second, // helps kill ghost Goroutines:
// http://stackoverflow.com/questions/10971800/golang-http-server-leaving-open-goroutines
//ErrorLog: nil, // suppresses errors from stderr
}
// In order to run these two forever blocking methods, we need goroutines
wg := &sync.WaitGroup{}
wg.Add(1)
go func() {
http_err := http_serv.ListenAndServe() // run forever
logger.Debug(http_err)
wg.Done()
}()
wg.Add(1)
go func() {
ssl_err := http_ssl_serv.ListenAndServeTLS(
server_configs["public_key"],
server_configs["private_key"],
) // run forever
logger.Debug(ssl_err)
wg.Done()
}()
wg.Wait() // beyond this line is reached when both servers stop
logger.Err("Server closing.");
}
; CouchDB Configuration Settings
; Custom settings should be made in this file. They will override settings
; in default.ini, but unlike changes made to default.ini, this file won't be
; overwritten on server upgrade.
[couchdb]
;max_document_size = 4294967296 ; bytes
[httpd]
;port = 5984
;bind_address = 127.0.0.1
; Options for the MochiWeb HTTP server.
;server_options = [{backlog, 128}, {acceptor_pool_size, 16}]
; For more socket options, consult Erlang's module 'inet' man page.
;socket_options = [{recbuf, 262144}, {sndbuf, 262144}, {nodelay, true}]
; Uncomment next line to trigger basic-auth popup on unauthorized requests.
;WWW-Authenticate = Basic realm="administrator"
; Uncomment next line to set the configuration modification whitelist. Only
; whitelisted values may be changed via the /_config URLs. To allow the admin
; to change this value over HTTP, remember to include {httpd,config_whitelist}
; itself. Excluding it from the list would require editing this file to update
; the whitelist.
;config_whitelist = [{httpd,config_whitelist}, {log,level}, {etc,etc}]
[query_servers]
;nodejs = /usr/local/bin/couchjs-node /path/to/couchdb/share/server/main.js
[httpd_global_handlers]
;_google = {couch_httpd_proxy, handle_proxy_req, <<"http://www.google.com">>}
[couch_httpd_auth]
; If you set this to true, you should also uncomment the WWW-Authenticate line
; above. If you don't configure a WWW-Authenticate header, CouchDB will send
; Basic realm="server" in order to prevent you getting logged out.
; require_valid_user = false
timeout = 360000
[log]
;level = debug
[log_level_by_module]
; In this section you can specify any of the four log levels 'none', 'info',
; 'error' or 'debug' on a per-module basis. See src/*/*.erl for various
; modules.
;couch_httpd = error
[os_daemons]
; For any commands listed here, CouchDB will attempt to ensure that
; the process remains alive. Daemons should monitor their environment
; to know when to exit. This can most easily be accomplished by exiting
; when stdin is closed.
;foo = /path/to/command -with args
go_server = /usr/local/lib/goserver/goserver
[daemons]
; enable SSL support by uncommenting the following line and supply the PEM's below.
; the default ssl port CouchDB listens on is 6984
; httpsd = {couch_httpd, start_link, [https]}
[go_server]
; go_server configs can go here. Defaults listed below:
username = couchdb_username
password = couchdb_password
couchURL = http://localhost:5984
static_web_assets = /usr/local/lib/goserver/www
http_port = :8080
ssl_port = :4433
public_key = /usr/local/lib/goserver/ssl/server.crt
private_key = /usr/local/lib/goserver/ssl/server.key
[ssl]
;cert_file = /full/path/to/server_cert.pem
;key_file = /full/path/to/server_key.pem
;password = somepassword
; set to true to validate peer certificates
verify_ssl_certificates = false
; Path to file containing PEM encoded CA certificates (trusted
; certificates used for verifying a peer certificate). May be omitted if
; you do not want to verify the peer.
;cacert_file = /full/path/to/cacertf
; The verification fun (optional) if not specified, the default
; verification fun will be used.
;verify_fun = {Module, VerifyFun}
; maximum peer certificate depth
ssl_certificate_max_depth = 1
; To enable Virtual Hosts in CouchDB, add a vhost = path directive. All requests to
; the Virual Host will be redirected to the path. In the example below all requests
; to http://example.com/ are redirected to /database.
; If you run CouchDB on a specific port, include the port number in the vhost:
; example.com:5984 = /database
[vhosts]
;example.com = /database/
[update_notification]
;unique notifier name=/full/path/to/exe -with "cmd line arg"
; To create an admin account uncomment the '[admins]' section below and add a
; line in the format 'username = password'. When you next start CouchDB, it
; will change the password to a hash (so that your passwords don't linger
; around in plain-text files). You can add more admin accounts with more
; 'username = password' lines. Don't forget to restart CouchDB after
; changing this.
[admins]
;admin = mysecretpassword
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment