Пример #1
0
func SetupImgServer() http.Handler {

	store, err := btcdn.NewFsStore("../fixtures")
	if err != nil {
		log.Fatal(err)
	}

	pr, err := processor.New()
	if err != nil {
		log.Fatal(err)
	}

	imgSrv, err := btcdn.NewImageServer(store, pr, "../fixtures/error.png")
	if err != nil {
		log.Fatal(err)
	}

	return imgSrv
}
Пример #2
0
func main() {

	maxProcs := runtime.NumCPU()
	runtime.GOMAXPROCS(maxProcs)

	var (
		listen_host        string
		fs_basepath        string
		fs_cachepath       string
		http_origin        string
		error_imgpath      string
		secret             string
		rate_limit_by_path int
		rate_limit_bursts  int
		concurrency        int
		newrelic_key       string
	)

	flag.StringVar(&listen_host, "listen", "localhost:3000", "HTTP host:port to listen for incoming requests")
	flag.StringVar(&fs_basepath, "basepath", "", "File system base path to lookup images")
	flag.StringVar(&fs_cachepath, "cachepath", "", "File system base path to cache images")
	flag.StringVar(&http_origin, "httporigin", "", "HTTP endpoint to lookup origin images")
	flag.StringVar(&error_imgpath, "errorimgpath", "./fixtures/error.png", "Error image path in local filesystem")
	flag.StringVar(&secret, "secret", "", "Secret used to check image signature")
	flag.StringVar(&newrelic_key, "newrelic", "", "NewRelic application key")
	flag.IntVar(&rate_limit_by_path, "ratelimit", 0, "Rate limit. Concurrent images per request path")
	flag.IntVar(&rate_limit_bursts, "bursts", 5, "Rate limits bursts")
	flag.IntVar(&concurrency, "concurrency", 0, "Max concurrent requests")

	flag.Parse()

	var store btcdn.Store
	var storeErr error
	var newrelic *gorelic.Agent

	if fs_basepath != "" {
		store, storeErr = btcdn.NewFsStore(fs_basepath)
	} else {
		store, storeErr = btcdn.NewHttpStore(http_origin)
	}

	if storeErr != nil {
		log.Fatal(storeErr)
	}

	pr, err := processor.New()
	if err != nil {
		log.Fatal(err)
	}

	imgSrv, err := btcdn.NewImageServer(store, pr, error_imgpath)
	if err != nil {
		log.Fatal(err)
	}

	router := mux.NewRouter()

	var srv http.Handler
	srv = router

	if secret == "" { // no security
		log.Println("No secret. Using ImageServer with no DoS protection")
		router.HandleFunc("/", imgSrv.ServeHTTP)
	} else { // secure server
		log.Println("Secret provided. Using ImageServer with DoS protection")
		srv = btcdn.NewSecureServer(imgSrv, secret, router)
	}

	// Only cache named sizes
	// to the filesystem for now
	if fs_cachepath != "" {
		log.Println("Caching named sizes to", fs_cachepath)
		cachedEndpoint := btcdn.NewCachedEndpoint(imgSrv, fs_cachepath)
		srv = btcdn.NewNamedSizesServer(cachedEndpoint, router)
	} else {
		srv = btcdn.NewNamedSizesServer(imgSrv, router)
	}

	// Setup rate-limited server
	if rate_limit_by_path > 0 {
		store, err := tstore.New(65536)
		if err != nil {
			log.Fatal(err)
		}
		quota := throttled.RateQuota{throttled.PerSec(rate_limit_by_path), rate_limit_bursts}
		rateLimiter, err := throttled.NewGCRARateLimiter(store, quota)
		if err != nil {
			log.Fatal(err)
		}

		httpRateLimiter := throttled.HTTPRateLimiter{
			RateLimiter: rateLimiter,
			VaryBy:      &throttled.VaryBy{Path: true},
		}

		log.Println("Rate limiting by path with ", rate_limit_by_path, "reqs. per second with bursts of ", rate_limit_bursts)
		srv = httpRateLimiter.RateLimit(srv)
	}

	// http.HandleFunc("/favicon.ico", FaviconHandler)

	var concurrencyPrompt string

	if concurrency > 0 {
		srv = httpool.Wrap(srv, concurrency)
		concurrencyPrompt = fmt.Sprintf("concurrency: %d", concurrency)
	}

	if newrelic_key != "" {
		newrelic = gorelic.NewAgent()
		newrelic.NewrelicLicense = newrelic_key
		newrelic.NewrelicName = "Btcdn (Go image resizer"
		newrelic.CollectHTTPStat = true

		newrelic.Run()

		srv = newrelic.WrapHTTPHandler(srv)
		log.Println("Newrelic support enabled")
	}

	log.Println("Serving on", listen_host, "cores:", maxProcs, "store:", concurrencyPrompt, store.String(), "error img:", error_imgpath)
	log.Fatal(http.ListenAndServe(listen_host, srv))
}