Skip to content

Instantly share code, notes, and snippets.

@3d0c
Created May 10, 2015 09:29
Show Gist options
  • Save 3d0c/b73f80564510d93f6373 to your computer and use it in GitHub Desktop.
Save 3d0c/b73f80564510d93f6373 to your computer and use it in GitHub Desktop.
reverse proxy example
package main
import (
"file-api/oid"
c "file-api/proxy/controllers"
"file-api/proxy/models"
. "file-api/proxy/utils"
"github.com/3d0c/martini-contrib/binding"
"github.com/3d0c/martini-contrib/config"
"github.com/3d0c/martini-contrib/encoder"
"github.com/codegangsta/martini"
"log"
"net/http"
"net/http/httputil"
"net/url"
"strings"
)
func init() {
log.SetFlags(log.Lshortfile | log.Ldate | log.Ltime)
config.Init("./proxy.json")
config.LoadInto(ProxyCfg)
oid.Nodes = &oid.NodesCounter{Total: ProxyCfg.NodesCount()}
}
// Cache-Control: max-age=2592000
// Pragma: public
// Cache-Control: public
func main() {
m := martini.New()
route := martini.NewRouter()
m.Use(func(c martini.Context, w http.ResponseWriter) {
c.MapTo(encoder.JsonEncoder{}, (*encoder.Encoder)(nil))
w.Header().Set("Content-Type", "application/json")
})
// some CORS stuff
m.Use(func(w http.ResponseWriter, req *http.Request) {
if origin := req.Header.Get("Origin"); origin != "" {
w.Header().Add("Access-Control-Allow-Origin", origin)
} else {
w.Header().Add("Access-Control-Allow-Origin", "*")
}
w.Header().Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
w.Header().Add("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token")
w.Header().Add("Access-Control-Expose-Headers", "Mv-Length, Mv-Dim, Mv-Dim-Max")
w.Header().Add("Cache-Control", "max-age=2592000")
w.Header().Add("Pragma", "public")
w.Header().Add("Cache-Control", "public")
})
// Preflight - 200 OK.
route.Options("/**")
route.Get("/files", binding.Form(models.UrlOptions{}), c.FilesFind)
route.Post("/files", proxyMap, func(p *httputil.ReverseProxy, w http.ResponseWriter, r *http.Request) {
p.ServeHTTP(w, r)
})
m.Action(route.Handle)
log.Printf("Proxy waiting for connections on %v...\n", ProxyCfg.ListenOn())
go func() {
if err := http.ListenAndServe(ProxyCfg.ListenOn(), m); err != nil {
log.Fatal(err)
}
}()
if err := http.ListenAndServeTLS(ProxyCfg.HttpsOn(), ProxyCfg.SSLCert(), ProxyCfg.SSLKey(), m); err != nil {
log.Fatal(err)
}
}
func proxyMap(ctx martini.Context, req *http.Request) {
var nodeId int32 = oid.NewObjectId().NodeId()
if strings.HasPrefix(req.URL.Path, "/files/") {
p := strings.Split(req.URL.Path, "/")
if len(p) == 3 && oid.IsObjectIdHex(p[2]) {
nodeId = oid.ObjectIdHex(p[2]).NodeId()
}
}
remote, err := url.Parse(ProxyCfg.Node(nodeId).GetAddress())
if err != nil {
panic(err)
}
proxy := httputil.NewSingleHostReverseProxy(remote)
ctx.Map(proxy)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment