package main import ( "flag" "log/slog" "net/http" "net/http/pprof" "os" "path/filepath" "time" cacheproxy "git.jeffthecoder.xyz/guochao/cache-proxy" "git.jeffthecoder.xyz/guochao/cache-proxy/pkgs/middleware" "git.jeffthecoder.xyz/guochao/cache-proxy/pkgs/middleware/handlerctx" "git.jeffthecoder.xyz/guochao/cache-proxy/pkgs/middleware/httplog" "git.jeffthecoder.xyz/guochao/cache-proxy/pkgs/middleware/recover" "github.com/getsentry/sentry-go" "gopkg.in/yaml.v3" ) var ( configFilePath = "config.yaml" logLevel = "info" sentrydsn = "" pprofEnabled = false ) func init() { if v, ok := os.LookupEnv("CONFIG_PATH"); ok { configFilePath = v } if v, ok := os.LookupEnv("LOG_LEVEL"); ok { logLevel = v } flag.StringVar(&configFilePath, "config", configFilePath, "path to config file") flag.StringVar(&logLevel, "log-level", logLevel, "log level. (trace, debug, info, warn, error)") } func configFromFile(path string) (*cacheproxy.Config, error) { file, err := os.Open(path) if err != nil { return nil, err } defer file.Close() config := &cacheproxy.Config{ Upstreams: []cacheproxy.Upstream{ { Server: "https://mirrors.ustc.edu.cn", }, }, Storage: cacheproxy.Storage{ Type: "local", Local: &cacheproxy.LocalStorage{ Path: "./data", TemporaryFilePattern: "temp.*", Accel: cacheproxy.Accel{ RespondWithHeaders: []string{"X-Sendfile", "X-Accel-Redirect"}, }, }, }, Misc: cacheproxy.MiscConfig{ FirstChunkBytes: 1024 * 1024 * 50, ChunkBytes: 1024 * 1024, }, Cache: cacheproxy.Cache{ RefreshAfter: time.Hour, }, } if err := yaml.NewDecoder(file).Decode(&config); err != nil { return nil, err } if config.Storage.Local != nil { localPath, err := filepath.Abs(config.Storage.Local.Path) if err != nil { return nil, err } config.Storage.Local.Path = localPath } return config, nil } func main() { flag.Parse() lvl := slog.LevelInfo if err := lvl.UnmarshalText([]byte(logLevel)); err != nil { slog.With("error", err).Error("failed to parse log level") os.Exit(-1) } else { slog.SetLogLoggerLevel(lvl) } if sentrydsn != "" { if err := sentry.Init(sentry.ClientOptions{ Dsn: sentrydsn, }); err != nil { slog.With("dsn", sentrydsn, "error", err).Error("failed to setup sentry") os.Exit(-1) } defer sentry.Flush(time.Second * 3) } config, err := configFromFile(configFilePath) if err != nil { panic(err) } ch := make(chan any, 10) for idx := 0; idx < 10; idx += 1 { ch <- idx } server := cacheproxy.NewServer(*config) mux := http.NewServeMux() mux.HandleFunc("GET /", server.HandleRequestWithCache) if pprofEnabled { mux.HandleFunc("GET /debug/pprof/", pprof.Index) mux.HandleFunc("GET /debug/pprof/cmdline", pprof.Cmdline) mux.HandleFunc("GET /debug/pprof/profile", pprof.Profile) mux.HandleFunc("GET /debug/pprof/symbol", pprof.Symbol) mux.HandleFunc("GET /debug/pprof/trace", pprof.Trace) } slog.With("addr", ":8881").Info("serving app") if err := http.ListenAndServe(":8881", middleware.Use(mux, recover.Recover(), handlerctx.FindHandler(mux), httplog.Log(httplog.Config{LogStart: true, LogFinish: true}), )); err != nil { slog.With("error", err).Error("failed to start server") os.Exit(-1) } }