func main() { var err error log := log.New(os.Stdout, "- ", log.LstdFlags) // Initialize boxes staticBox = rice.MustFindBox("static") templateBox = rice.MustFindBox("templates") log.Println("Listen host: " + cfg.Host) log.Println("Listen port: " + strconv.Itoa(cfg.Port)) log.Println("Read timeout: " + strconv.Itoa(cfg.ReadTimeout) + " seconds") log.Println("Write timeout: " + strconv.Itoa(cfg.WriteTimeout) + " seconds") log.Println("Max header size: " + strconv.Itoa(cfg.MaxHeaderBytes) + " bytes") log.Println("Access log file: " + cfg.AccessLog) log.Println("Cache invalidation enabled: " + strconv.FormatBool(cfg.CacheInvalidation)) log.Println("Workers: " + strconv.Itoa(cfg.Workers)) log.Println("Expiration time: " + strconv.FormatInt(cfg.Expiration, 10) + " seconds") log.Println("Files directory: " + cfg.Filedir) log.Println("Temp directory: " + cfg.Tempdir) //log.Println("Log directory: " + cfg.Logdir) log.Println("Baseurl: " + cfg.Baseurl) var trigger = cfg.TriggerNewBin if trigger == "" { trigger = "Not set" } log.Println("Trigger - New bin: " + trigger) trigger = cfg.TriggerUploadFile if trigger == "" { trigger = "Not set" } log.Println("Trigger - Upload file: " + trigger) trigger = cfg.TriggerDownloadBin if trigger == "" { trigger = "Not set" } log.Println("Trigger - Download bin: " + trigger) trigger = cfg.TriggerDownloadFile if trigger == "" { trigger = "Not set" } log.Println("Trigger - Download file: " + trigger) trigger = cfg.TriggerDeleteBin if trigger == "" { trigger = "Not set" } log.Println("Trigger - Delete bin: " + trigger) trigger = cfg.TriggerDeleteFile if trigger == "" { trigger = "Not set" } log.Println("Trigger - Delete file: " + trigger) //fmt.Println("Trigger Expired bin: " + cfg.TriggerExpiredBin) accessLogWriter, err := os.OpenFile(cfg.AccessLog, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666) if err != nil { fmt.Println("Unable to open access log file: " + err.Error()) os.Exit(2) } m = metrics.Init() startTime := time.Now().UTC() backend, err = fs.InitBackend(cfg.Baseurl, cfg.Filedir, cfg.Tempdir, cfg.Expiration, log) if err != nil { log.Fatalln(err.Error()) } finishTime := time.Now().UTC() elapsedTime := finishTime.Sub(startTime) backend.Log.Println("Backend initialized in: " + elapsedTime.String()) log.Println("Backend: " + backend.Info()) log.Println("Filebin server starting...") // Start dispatcher that will handle all background processing model.StartDispatcher(cfg.Workers, WorkQueue, &backend) // Sending all files through the batch process to ensure thumbnails // are generated. for _, bin := range backend.GetBins() { files := backend.GetFiles(bin) for _, filename := range files { j := model.Job{} j.Filename = filename j.Bin = bin j.Log = log j.Cfg = &cfg WorkQueue <- j } } router := mux.NewRouter() router.Handle("/static/{path:.*}", http.StripPrefix("/static/", http.FileServer(staticBox.HTTPBox()))).Methods("GET", "HEAD") http.Handle("/", httpInterceptor(router)) // Accept trailing slashes. // Disabling this feature for now since it might not be needed. Try to // find some other way of accepting trailing slashes where appropriate // instead of globally. //router.StrictSlash(true) // Skip reqHandler to avoid logging of requests to this endpoint router.HandleFunc("/filebin-status", api.FilebinStatus).Methods("GET", "HEAD") router.HandleFunc("/admin", basicAuth(reqHandler(api.AdminDashboard))).Methods("GET", "HEAD") router.HandleFunc("/admin/events", basicAuth(reqHandler(api.AdminEvents))).Methods("GET", "HEAD") router.HandleFunc("/admin/bins", basicAuth(reqHandler(api.AdminBins))).Methods("GET", "HEAD") router.HandleFunc("/admin/counters", basicAuth(reqHandler(api.AdminCounters))).Methods("GET", "HEAD") router.HandleFunc("/readme", reqHandler(api.Readme)).Methods("GET", "HEAD") router.HandleFunc("/", reqHandler(api.NewBin)).Methods("GET", "HEAD") router.HandleFunc("/", reqHandler(api.Upload)).Methods("POST") router.HandleFunc("/archive/{bin:[A-Za-z0-9_-]+}/{format:[a-z]+}", reqHandler(api.FetchArchive)).Methods("GET", "HEAD") router.HandleFunc("/album/{bin:[A-Za-z0-9_-]+}", reqHandler(api.FetchAlbum)).Methods("GET", "HEAD") router.HandleFunc("/{bin:[A-Za-z0-9_-]+}", reqHandler(api.FetchBin)).Methods("GET", "HEAD") router.HandleFunc("/{bin:[A-Za-z0-9_-]+}", reqHandler(api.DeleteBin)).Methods("DELETE") router.HandleFunc("/{bin:[A-Za-z0-9_-]+}/{filename:.+}", reqHandler(api.FetchFile)).Methods("GET", "HEAD") router.HandleFunc("/{bin:[A-Za-z0-9_-]+}/{filename:.+}", reqHandler(api.DeleteFile)).Methods("DELETE") router.HandleFunc("/{path:.*}", reqHandler(api.PurgeHandler)).Methods("PURGE") logRouter := handlers.CombinedLoggingHandler(accessLogWriter, router) server := &http.Server{ Addr: cfg.Host + ":" + strconv.Itoa(cfg.Port), Handler: logRouter, ReadTimeout: time.Duration(cfg.ReadTimeout) * time.Second, WriteTimeout: time.Duration(cfg.WriteTimeout) * time.Second, MaxHeaderBytes: cfg.MaxHeaderBytes, } err = server.ListenAndServe() if err != nil { log.Panicln(err.Error()) } }
func Upload(w http.ResponseWriter, r *http.Request, cfg config.Configuration, ctx model.Context) { r.Close = true bin := r.Header.Get("bin") if err := verifyBin(bin); err != nil { http.Error(w, "Invalid bin", 400) return } b, err := ctx.Backend.GetBinMetaData(bin) if err == nil { if b.Expired { http.Error(w, "This bin expired "+b.ExpiresReadable+".", 410) return } } filename := sanitizeFilename(r.Header.Get("filename")) if err := verifyFilename(filename); err != nil { http.Error(w, "Invalid filename", 400) return } ctx.Metrics.Incr("current-upload") defer ctx.Metrics.Decr("current-upload") event := ctx.Events.New(ctx.RemoteAddr, []string{"file", "upload"}, bin, filename) defer event.Done() if i, err := strconv.Atoi(r.Header.Get("content-length")); err == nil { event.Update("Size: "+humanize.Bytes(uint64(i)), 0) } if ctx.Backend.BinExists(bin) == false { if cfg.TriggerNewBin != "" { ctx.Log.Println("Executing trigger: New bin") triggerNewBinHandler(cfg.TriggerNewBin, bin) } } f, err := ctx.Backend.UploadFile(bin, filename, r.Body) if err != nil { ctx.Log.Println(err) http.Error(w, "Internal Server Error", http.StatusInternalServerError) event.Update(err.Error(), 2) return } ctx.Metrics.Incr("total-upload") if cfg.TriggerUploadFile != "" { ctx.Log.Println("Executing trigger: Uploaded file") triggerUploadFileHandler(cfg.TriggerUploadFile, f.Bin, f.Filename) } // Purging any old content if cfg.CacheInvalidation { for _, l := range f.Links { if err := shared.PurgeURL(l.Href, ctx.Log); err != nil { ctx.Log.Println(err) } } } j := model.Job{} j.Filename = f.Filename j.Bin = f.Bin j.Log = ctx.Log j.Cfg = &cfg ctx.WorkQueue <- j w.Header().Set("Content-Type", "application/json") var status = 201 output.JSONresponse(w, status, f, ctx) }