Created
June 12, 2016 22:43
-
-
Save elico/9bb3da6b7937ce09a0c2d91637b3be5c to your computer and use it in GitHub Desktop.
A reverse http caching proxy with example of how to override traffic to pass the cache.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"flag" | |
"github.com/lox/httpcache" | |
"github.com/lox/httpcache/httplog" | |
"log" | |
"net/http" | |
"net/http/httputil" | |
"os" | |
"strings" | |
) | |
const ( | |
defaultListen = "0.0.0.0:8080" | |
defaultDir = "./cachedata" | |
) | |
var ( | |
listen string | |
useDisk bool | |
private bool | |
dir string | |
dumpHttp bool | |
verbose bool | |
) | |
func hanlderToFunc(cache http.Handler, proxy http.Handler) http.HandlerFunc { | |
return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { | |
switch { | |
case (req.Method == "GET" && strings.HasPrefix(req.URL.Path, "/static")): | |
cache.ServeHTTP(res, req) | |
return | |
default: | |
proxy.ServeHTTP(res, req) | |
return | |
} | |
}) | |
} | |
func init() { | |
flag.StringVar(&listen, "listen", defaultListen, "the host and port to bind to") | |
flag.StringVar(&dir, "dir", defaultDir, "the dir to store cache data in, implies -disk") | |
flag.BoolVar(&useDisk, "disk", false, "whether to store cache data to disk") | |
flag.BoolVar(&verbose, "v", false, "show verbose output and debugging") | |
flag.BoolVar(&private, "private", false, "make the cache private") | |
flag.BoolVar(&dumpHttp, "dumphttp", false, "dumps http requests and responses to stdout") | |
flag.Parse() | |
if verbose { | |
httpcache.DebugLogging = true | |
} | |
} | |
func main() { | |
proxy := &httputil.ReverseProxy{ | |
Director: func(r *http.Request) { | |
r.URL.Scheme = "http" | |
r.URL.Host = "127.0.0.1:80" | |
}, | |
} | |
var cache httpcache.Cache | |
if useDisk && dir != "" { | |
log.Printf("storing cached resources in %s", dir) | |
if err := os.MkdirAll(dir, 0700); err != nil { | |
log.Fatal(err) | |
} | |
var err error | |
cache, err = httpcache.NewDiskCache(dir) | |
if err != nil { | |
log.Fatal(err) | |
} | |
} else { | |
cache = httpcache.NewMemoryCache() | |
} | |
handler := httpcache.NewHandler(cache, proxy) | |
handler.Shared = !private | |
if verbose { | |
respLogger := httplog.NewResponseLogger(handler) | |
respLogger.DumpRequests = dumpHttp | |
respLogger.DumpResponses = dumpHttp | |
respLogger.DumpErrors = dumpHttp | |
log.Printf("listening on http://%s", listen) | |
log.Fatal(http.ListenAndServe(listen, hanlderToFunc(respLogger, proxy))) | |
} else { | |
log.Printf("listening on http://%s", listen) | |
log.Fatal(http.ListenAndServe(listen, hanlderToFunc(handler, proxy))) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment