// NewCachingSingleHostReverseProxy constructs a caching reverse proxy handler for // target. If cache is nil, a volatile, in-memory cache is used. func NewCachingSingleHostReverseProxy(target *url.URL, cache httpcache.Cache) *httputil.ReverseProxy { proxy := NewSingleHostReverseProxy(target) if cache == nil { cache = httpcache.NewMemoryCache() } proxy.Transport = httpcache.NewTransport(cache) return proxy }
func main() { flag.Usage = func() { fmt.Fprintf(os.Stderr, "apiproxy proxies and mocks HTTP APIs.\n\n") fmt.Fprintf(os.Stderr, "Usage:\n\n") fmt.Fprintf(os.Stderr, "\tapiproxy [options] url\n\n") fmt.Fprintf(os.Stderr, "url is the base URL of the HTTP server to proxy.\n\n") fmt.Fprintf(os.Stderr, "The options are:\n\n") flag.PrintDefaults() fmt.Fprintln(os.Stderr) fmt.Fprintln(os.Stderr) fmt.Fprintf(os.Stderr, "Example usage:\n\n") fmt.Fprintf(os.Stderr, "\tTo run a caching proxy at http://localhost:8080 with target http://example.com:\n") fmt.Fprintf(os.Stderr, "\t $ apiproxy http://example.com\n\n") fmt.Fprintf(os.Stderr, "\t... and never revalidate cached responses:\n") fmt.Fprintf(os.Stderr, "\t $ apiproxy -never-revalidate http://example.com\n\n") fmt.Fprintf(os.Stderr, "\t... and only revalidate cached responses older than an hour:\n") fmt.Fprintf(os.Stderr, "\t $ apiproxy -only-revalidate-older-than=1h http://example.com\n\n") fmt.Fprintln(os.Stderr) os.Exit(1) } flag.Parse() if flag.NArg() != 1 { flag.Usage() } targetURL, err := url.Parse(flag.Arg(0)) if err != nil { fmt.Fprintf(os.Stderr, "Error parsing URL %q: %s\n", flag.Arg(0), err) os.Exit(1) } var onlyRevalOlderThan time.Duration if *onlyRevalOlderThanStr != "" { onlyRevalOlderThan, err = time.ParseDuration(*onlyRevalOlderThanStr) if err != nil { fmt.Fprintf(os.Stderr, "Failed to parse duration %q: %s\n", *onlyRevalOlderThanStr, err) os.Exit(1) } } proxy := apiproxy.NewCachingSingleHostReverseProxy(targetURL, httpcache.NewMemoryCache()) cachingTransport := proxy.Transport.(*httpcache.Transport) cachingTransport.Transport = &apiproxy.RevalidationTransport{ Check: apiproxy.ValidatorFunc(func(url *url.URL, age time.Duration) bool { if *neverRevalidate { return true } if *onlyRevalOlderThanStr != "" { return age <= onlyRevalOlderThan } return false }), } http.Handle("/", handlers.CombinedLoggingHandler(os.Stdout, proxy)) fmt.Fprintf(os.Stderr, "Starting proxy on %s with target %s\n", *bindAddr, targetURL.String()) err = http.ListenAndServe(*bindAddr, nil) if err != nil { log.Fatalf("ListenAndServe: %s", err) } }